Komplett usichtbares JFRame

fm it

Mitglied
Hallo,
Ich programmiere grad ein Programm für das ich ein komplett unsichtbares JFrame brauche.
Mit setVisible(false); geht es ja nicht da dann das Programm nicht ausgeführt wird. Gibt es einen anderen Befehl oder geht das mit Swing nicht ?
 
Hallo,

schau mal hier:

Java:
package de.tutorials;

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Window;
import java.lang.reflect.Method;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import javax.swing.JFrame;
import javax.swing.JTree;

public class TransparentJFrame extends JFrame {

	public TransparentJFrame() {
		super("TransparentJFrame");
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setUndecorated(true);
		setLocationRelativeTo(null); // CENTER on Screen

		JTree comp = new JTree();
		comp.setPreferredSize(new Dimension(400, 300));
		add(comp);
		pack();

		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
			int i = 0;

			public void run() {
				i++;

				final float transparency = 1.f / (i);
				EventQueue.invokeLater(new Runnable() {
					public void run() {
						try {
							Class<?> awtUtilitiesClass = getClass().getClassLoader().loadClass("com.sun.awt.AWTUtilities");
							
							// oder per AWTUtilities.setWindowOpaque(frame, false)
							//siehe auch: http://java.sun.com/developer/technicalArticles/GUI/translucent_shaped_windows/#Setting-the-Opacity-Level-of-a-Window
							Method mSetWindowOpacity = awtUtilitiesClass.getMethod("setWindowOpacity",Window.class, float.class);
							System.out.println(i + " " + transparency);
							mSetWindowOpacity.invoke(null,TransparentJFrame.this,Float.valueOf(transparency));
						} catch (Exception ex) {
							ex.printStackTrace();
						}
					}
				});
				i %= 5;

			}
		}, 1, 1, TimeUnit.SECONDS);

	}

	public static void main(String[] args) {
		new TransparentJFrame().setVisible(true);

	}

}

Gruß Tom
 
Das fenster ist immer noch zu sehen. Ich brauche das frame auch nur um andere Java befehle zu starten. In dem Fenster soll sonst nichts zu sehen sein. Könnte man java dateien auch komplett ohne fenster ausführen also auch ohne console ?
 
Ich will eig. nur ein paar java befehle starten die zum bespiel emails checken und mir die in einer textdatei speichert. Ich breucht edafür ja eig. kein frame. Aber ich habe net gelernt wie man programme ohne die console in eclipse oder einem frame ausgibt ich weiß gar net ob das geht.
 
Welche Befehle brauchst du denn? Etwas, was direkt von der graphischen Oberfläche abhängt? Wenn nein, dann starte doch einfach einen Thread, setze ihn als nicht-deamon und lege ihn schlafen. Das Problem an deinem Programm ist wohl folgendes: Wenn die main()-Methode abgearbeitet ist und kein Fenster angezeigt wird (i.e. kein Thread läuft, der noch etwas wichtiges tut (und daher kein Deamon ist) wie z.B. auf (graphische) Events hören, wird die JVM beendet.
 
Ich will nur eine klasse aufrufen die nur dinge in der Console ausgibt. Die Console braucht das Programm jedoch auch nicht. Wie macht man so was mit nicht-deamon.
 
Hallo,

so wie ich das sehe, möchtest du eine Anwendung im Hintergrund laufen lassen.
Diese Anwendung hat eigentlich keine User Interface Interaktion (außer, dass die Anwendung gestartet werden muss) - darüber hinaus soll man sie wohl auch noch wieder beenden können (via User Interface)?.

In diesem Szenario empfehle ich dir folgendes:
0) Definiere in deiner Anwendung ein Systemtray-Menu (siehe Beispiel) (wenigstens mit der Möglichkeit zum beenden der kleinen Anwendung)
1) Erzeuge ein ausführbares Jar Archiv (runnable jar archive *)) z.Bsp. mit dem Eclipse Export -> Java -> Export as Runnable Jar archive und speichere dies in einem Verzeichnis, z.Bsp.: c:\temp\app.jar
2) Lege dir auf dem Desktop eine Verknüpfung mit folgendem Ziel an:
Code:
javaw -jar c:\temp\app.jar
3) Anschließend sollte sich deine Anwendung ohne ein assoziiertes Konsolenfenster starten.
-> Vorsicht Sysout / Syserr gehen hierbei ins leere!
-> hier könnte man noch System.setOut(errOutStream); u. System.setErr(errOutStream); entsprechend umbiegen.

*) Wenn du absolut kein runnable Jar erstellen willst geht es auch über:
Code:
 javaw -cp c:\TEMP\app.jar de.tutorials.App
... das müsstest du dann auch bei dem Ziel der Verknüpfung eintragen.

Der Trick ist hier javaw anstatt den java Launcher zu verwenden. Dieser Launcher assoziiert kein Konsolenfenster mit dem Java Prozess.

(Wenn deine Java Umgebung richtig eingerichtet ist reicht bei einem ausführbaren Jar eigentlich schon ein "Doppelklick auf das Jar" bzw. nur eine Verknüpfung mit dem jar)

Hier noch das kleine Beispiel:
Java:
package de.tutorials;

import java.awt.Dimension;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.TrayIcon.MessageType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.Date;

public class App {

	final static String cmdOp1 = "op1";
	final static String cmdExit = "exit";

	private TrayIcon systemTrayIcon;

	public static void main(String[] args) {
		new App().start();
	}

	private void start() {
		startUI();
	}

	protected void handleShowMessage() {
		systemTrayIcon.displayMessage("Title", "Message: " + new Date(),MessageType.INFO);
	}
	
	protected void handleExit() {
		shutdownUI();
	}
	
	protected void handleCommand(String command) {
		System.out.println("Do: " + command);
		if (cmdOp1.equals(command)) {
			handleShowMessage();
		} else if (cmdExit.equals(command)) {
			handleExit();
		}
	}

	private void shutdownUI() {
		removeSystemTrayIcon();
	}

	private void removeSystemTrayIcon() {
		if (systemTrayIcon != null) {
			SystemTray.getSystemTray().remove(systemTrayIcon);
		}
	}

	private void startUI() {
		if (SystemTray.isSupported()) {
			hookInitSystemTray();
		}
	}

	private void hookInitSystemTray() {
		try {
			SystemTray tray = SystemTray.getSystemTray();
			Dimension trayIconSize = tray.getTrayIconSize();
			systemTrayIcon = new TrayIcon(getTrayIconImage(trayIconSize),
					"Tooltip");
			tray.add(systemTrayIcon);
			systemTrayIcon.setPopupMenu(createPopupMenu(systemTrayIcon));

		} catch (Exception ex) {

		}
	}

	private BufferedImage getTrayIconImage(Dimension trayIconSize) {
		// Generate dummy try icon image
		return new BufferedImage(trayIconSize.width, trayIconSize.width,
				BufferedImage.TYPE_INT_RGB);
	}

	private PopupMenu createPopupMenu(final TrayIcon trayIcon) {
		PopupMenu menu = new PopupMenu("Menu");

		menu.add(createMenuItem("Nachricht ausgeben", cmdOp1));
		menu.add(createMenuItem("Beenden", cmdExit));

		menu.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				handleCommand(e.getActionCommand());
			}
		});

		return menu;
	}

	private MenuItem createMenuItem(String caption, String actionCommand) {
		MenuItem mi = new MenuItem(caption);
		mi.setActionCommand(actionCommand);
		return mi;
	}

}


Gruß Tom
 
Wenn du gar keine Ausgabe und kein Fenster und kein gar nichts brauchst, dann starte das Programm nicht mit java, sondern mit javaw.

Ein nicht-Dämon ist jeder zusätzlich gestartete Thread. Der Thread wird erst zu einem Dämon, wenn man ihn zum Dämon macht (Thread.setDaemon(boolean)). Der Sinn von Dämon-Threads ist, dass das Programm nicht auf diese achten muss, wenn es sich beenden will. Das ist aber nicht default, daher sollte jeder gestartete Thread von selbst blockieren. Voraussetzung ist natürlich, dass in ihm die run-Methode nicht verlassen wird, denn dann wird der Thread beendet und das Blockieren außer Gefecht gesetzt.

Aber ganz ehrlich ... Anstatt sowas merkwürdiges zu starten sollte man dann lieber in der main-Methode einfach eine Endlosschleife starten und gut ist, dann wird das Programm auch blockiert bzw. nicht beendet. Damit das aber nicht den Prozessor endlos belastet, sollte ein Schlafensphase eingebaut werden, sprich den Thread für eine gewisse Zeit schlafen legen. Die Zeitspanne richtet sich aber nach dem, was dein Tool machen soll. Also wenn es nur alle 5 min was checken soll, dann macht es ja Sinn die Zeitspanne auf 5 min zu setzen und nicht auf 1sek oder so.

EDIT:
Ach verdammt, Thomas war schneller xD
 
Zurück