Hallo,
ich möchte bei meinen Programm das Fenster nach einer Benutzereingabe (z. B. Button oder Menu) komplett sperren, dann die Berechnungen ausführen lassen und dann wieder das Fenster entsperren.
Ich habe dafür eine spezielle Klasse, die als GlasPane fungiert, sämtliche Eingaben abfangen kann, den Inhalt des Fensters leicht eingraut und ein Textfeld mit einer Nachricht besitzt.
Wenn ich die Methoden mAktiviereGlasPane(String p_Nachrichtentext) oder mDeaktiviereGlasPane() aber benutze, werden diese nicht oder nur unvollständig ausgeführt.
Ich denke, daß liegt daran, daß der Grafik-Thread seine Aufgabe irgendwie nicht komplett abarbeitet.
Hier ein kleines Testprogramm, welches die obrige Klasse verwendet:
Wie kriege ich das Programm dazu, das Fenster zuerst zu sperren und erst dann die Berechnung durchzuführen?
Ich habe schon mit invokeLater() und invokeAndWait() herumexperimentiert, aber bin zu keinem brauchbaren Ergebnis gekommen.
Eigendlich wollte ich mit dem Sperren/Entsperren des Fensters verhindern, daß ich komplizierte Threat-Geschichten machen muß.
Weiß vielleicht einer von euch eine Lösung?
Evtl. eine SwingWorker-Sache?
MfG
hansmueller
ich möchte bei meinen Programm das Fenster nach einer Benutzereingabe (z. B. Button oder Menu) komplett sperren, dann die Berechnungen ausführen lassen und dann wieder das Fenster entsperren.
Ich habe dafür eine spezielle Klasse, die als GlasPane fungiert, sämtliche Eingaben abfangen kann, den Inhalt des Fensters leicht eingraut und ein Textfeld mit einer Nachricht besitzt.
Java:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
/**
* <p>HKGlassPane</p>
* Eine HilfsKlasse, die dafür sorgen soll, daß das Hauptfenster nicht mehr
* bedient werden kann, wenn eine rechenintensive Aktion ausgeführt wird.
*
*
* @author hansmueller
*
*/
public class HKGlassPane extends JComponent
{
Border borderNachrichtenRahmen;
JLabel lbNachricht;
Color colNachrichtenHintergrund;
Color colGlassPaneHintergrund;
Color colGrundfarbe;
Boolean bAktiviert = false;
GlassPaneTastaturListener gptl;
String strNachrichtentext;
public HKGlassPane()
{
lbNachricht = new JLabel();//Wichtig, damit es zu keiner Nullpoint-Ecxeption beim setBackground kommt.
setOpaque(false);
colGrundfarbe = UIManager.getColor("inactiveCaptionBorder");
colGlassPaneHintergrund = new Color(colGrundfarbe.getRed(), colGrundfarbe.getGreen(), colGrundfarbe.getBlue(), 128);
setBackground(colGlassPaneHintergrund);
setLayout(new GridBagLayout());
//Das Nachrichten-JLabel:
add(lbNachricht, new GridBagConstraints());
lbNachricht.setOpaque(true);
borderNachrichtenRahmen = new EmptyBorder(10, 10, 10, 10);
lbNachricht.setBorder(borderNachrichtenRahmen);
//Maus-, Tastatur- und Fokus-Events müssen abgefangen werden.
addMouseListener(new MouseAdapter(){});
addMouseMotionListener(new MouseMotionAdapter(){});
gptl = new GlassPaneTastaturListener();
setFocusTraversalKeysEnabled(false);
}
/**
* Die HKGlassPane ist zwar transparent, aber um dem Fenster ein "gesperrtes" Aussehen
* zu geben, muß der Hintergrund gezeichnet werden.
*/
@Override
protected void paintComponent(Graphics g)
{
g.setColor(getBackground());
g.fillRect(0, 0, getSize().width, getSize().height);
}
/**
* Die Hintergrundfarbe des Nachrichten-JLabels ist die selbe wie beim GlassPane,
* jedoch ohne den Alpha-Kanal. (Dadurch wird es nicht transparent).
*/
@Override
public void setBackground(Color c)
{
super.setBackground(c);
colNachrichtenHintergrund = new Color(c.getRGB());
//System.out.println(c.toString());
lbNachricht.setBackground(colNachrichtenHintergrund);
}
/**
* Diese Methode ist dafür zuständig die Tastatur zu blockieren und wieder freizugeben.
*/
public void mbehandleAWTEventListener()
{
if(bAktiviert)
{
Toolkit.getDefaultToolkit().addAWTEventListener(gptl, AWTEvent.KEY_EVENT_MASK);
/*Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener()
{
public void eventDispatched(AWTEvent e)
{
if (e instanceof KeyEvent)
{
((KeyEvent) e).consume();
}
}
}, AWTEvent.KEY_EVENT_MASK);*/
}
else
{
Toolkit.getDefaultToolkit().removeAWTEventListener(gptl);
}
}
/**
* Macht das Fenster unbenutzbar und verändert den Mauszeiger in eine Sanduhr.
* @param p_Nachrichtentext Der Text wird mittig im Fenster angezeigt.
*
*/
public void mAktiviereGlasPane(String p_Nachrichtentext)
{
if (strNachrichtentext != null && strNachrichtentext.length() > 0)
{
lbNachricht.setVisible(true);
lbNachricht.setText(strNachrichtentext);
lbNachricht.setForeground(getForeground());
}
else
{
lbNachricht.setVisible(false);
}
bAktiviert = true;
setVisible(true);
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
mbehandleAWTEventListener();
requestFocusInWindow();
}
/**
* Macht das Fenster wieder benutzbar
*/
public void mDeaktiviereGlasPane()
{
bAktiviert = false;
mbehandleAWTEventListener();
setCursor(null);
setVisible(false);
}
/**
* Diese Klasse des AWTEventListeners enthält nur eine Methode, die sämtliche Eingaben über
* Tastatur ins Nirvana leitet.
*/
public class GlassPaneTastaturListener implements AWTEventListener
{
public void eventDispatched(AWTEvent event)
{
if (event instanceof KeyEvent)
{
((KeyEvent) event).consume();
}
}
}
}
Wenn ich die Methoden mAktiviereGlasPane(String p_Nachrichtentext) oder mDeaktiviereGlasPane() aber benutze, werden diese nicht oder nur unvollständig ausgeführt.
Ich denke, daß liegt daran, daß der Grafik-Thread seine Aufgabe irgendwie nicht komplett abarbeitet.
Hier ein kleines Testprogramm, welches die obrige Klasse verwendet:
Java:
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
public class MainProg
{
JFrame f;
JButton b1;
JButton b2;
HKGlassPane glas;
JMenuBar menuBar;
JMenu menu;
JMenuItem menuItem;
ListenerButtons lb;
public static void main(String[] args)
{
MainProg x = new MainProg();
}
public MainProg()
{
f = new JFrame("Test Glasspane");
glas = new HKGlassPane();
f.setGlassPane(glas);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLayout(new GridLayout(1, 2));
f.setPreferredSize(new Dimension(400, 300));
menuBar = new JMenuBar();
menu = new JMenu("Menu");
menuItem = new JMenuItem("Do nothing");
menu.add(menuItem);
menuBar.add(menu);
f.setJMenuBar(menuBar);
b1 = new JButton("Test 01");
b2 = new JButton("Test 02");
lb = new ListenerButtons(this);
b1.addActionListener(lb);
b2.addActionListener(lb);
menuItem.addActionListener(lb);
f.add(b1);
f.add(b2);
f.pack();
f.setVisible(true);
}
public class ListenerButtons implements ActionListener
{
HKGlassPane gp;
MainProg M;
public ListenerButtons(MainProg p_M)
{
gp = p_M.glas;
M = p_M;
}
@Override
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == b1)
{
System.out.println("Knopf 01");
gp.mAktiviereGlasPane("Bitte warten");
for(Integer i = 0; i < 999999999; i++);
{
System.out.println("Was zum Arbeiten.");
}
gp.mDeaktiviereGlasPane();
}
if(e.getSource() == b2)
{
System.out.println("Knopf 02");
}
if(e.getSource() == M.menuItem)
{
System.out.println("Menü");
gp.mAktiviereGlasPane("Bitte warten");
for(Integer i = 0; i < 999999999; i++);
{
System.out.println("Was zum Arbeiten.");
}
gp.mDeaktiviereGlasPane();
}
}
}
}
Wie kriege ich das Programm dazu, das Fenster zuerst zu sperren und erst dann die Berechnung durchzuführen?
Ich habe schon mit invokeLater() und invokeAndWait() herumexperimentiert, aber bin zu keinem brauchbaren Ergebnis gekommen.
Eigendlich wollte ich mit dem Sperren/Entsperren des Fensters verhindern, daß ich komplizierte Threat-Geschichten machen muß.
Weiß vielleicht einer von euch eine Lösung?
Evtl. eine SwingWorker-Sache?
MfG
hansmueller