java - salir - Nuevo JFrame se abre en estado deshabilitado cuando se abre con un clic de botón
hacer visible un jframe (1)
Estoy atrapado en una situación muy inusual. Tengo una clase "ScreenSizeSelector" que tiene un método ''getSelectedScreenSize''. El trabajo del método es crear una interfaz de usuario, el usuario arrastra la interfaz de usuario y el método devuelve el tamaño de la ventana.
Ahora estoy llamando al método de clase de las siguientes maneras:
- Una clase simple (sin GUI)
- En el botón, haga clic en un JFrame
En el primer caso, funciona perfectamente bien (es decir, se abre la ventana de selección de tamaño, el usuario arrastra, cambia el tamaño y devuelve las coordenadas de la ventana) pero en el segundo caso, se abre pero en modo desactivado el usuario no puede operación en la ventana, ni siquiera es capaz de cerrar la ventana.
Aquí está el código que estoy usando
Clase ScreenSizeSelector:
package screenrecorder;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.Border;
class ScreenSizeSelector {
private JFrame sizeSelectorWindow;
private JButton btnOk;
private Border emptyBorder;
private Rectangle screenArea = null;
private static Object lock = new Object();
public Rectangle getSelectedScreenSize(){
screenSizeSelectorUI();
Thread t = new Thread() {
public void run() {
synchronized(lock) {
while (sizeSelectorWindow.isVisible())
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t.start();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
return screenArea;
}
public void screenSizeSelectorUI() {
emptyBorder = BorderFactory.createEmptyBorder();
sizeSelectorWindow = new JFrame("Select screen area");
btnOk = new JButton("Start");
sizeSelectorWindow.setUndecorated(true);
sizeSelectorWindow.getRootPane().setWindowDecorationStyle(3);
sizeSelectorWindow.setBackground( new Color(0, 0, 0, 0) );
sizeSelectorWindow.setSize(400,400);
sizeSelectorWindow.addWindowListener(new WindowEventHandler());
sizeSelectorWindow.setAlwaysOnTop(true);
sizeSelectorWindow.setLocationRelativeTo(null);
btnOk.setToolTipText("Click this button after deciding the screen area");
btnOk.addActionListener(new ButtonEventHandler());
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
buttonPanel.setBackground(new Color(0,0,0,0));
buttonPanel.add(btnOk);
sizeSelectorWindow.add(buttonPanel,BorderLayout.SOUTH);
sizeSelectorWindow.setVisible(true);
sizeSelectorWindow.setEnabled(true);
}
class ButtonEventHandler implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
int x = (int)(sizeSelectorWindow.getBounds().getX());
int y = (int) (sizeSelectorWindow.getBounds().getY());
int width = sizeSelectorWindow.getWidth();
int height = sizeSelectorWindow.getHeight();
screenArea = new Rectangle(x,y,width,height);
sizeSelectorWindow.dispatchEvent(new WindowEvent(sizeSelectorWindow, WindowEvent.WINDOW_CLOSING));
}
}
class WindowEventHandler implements WindowListener{
@Override
public void windowOpened(WindowEvent e) {
}
@Override
public void windowClosing(WindowEvent e) {
synchronized (lock) {
sizeSelectorWindow.setVisible(false);
lock.notify();
}
}
@Override
public void windowClosed(WindowEvent e) {
}
@Override
public void windowIconified(WindowEvent e) {
sizeSelectorWindow.setState(JFrame.NORMAL);
Toolkit.getDefaultToolkit().beep();
}
@Override
public void windowDeiconified(WindowEvent e) {}
@Override
public void windowActivated(WindowEvent e) {}
@Override
public void windowDeactivated(WindowEvent e) {}
}
}
Clase Test1:
package screenrecorder;
import java.awt.Rectangle;
public class Test1{
public static void main(String[] args){
System.out.println(new ScreenSizeSelector().getSelectedScreenSize());
}
}
Clase Test2:
package screenrecorder;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Test2 extends JFrame{
public Test2(){
JButton btn = new JButton("Click ME");
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(new ScreenSizeSelector().getSelectedScreenSize());
}
});
getContentPane().add(btn);
setSize(100,100);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args){
new Test2();
}
}
Cualquier ayuda es apreciada.
cuando hace clic en el botón, el oyente de acción espera a que getSelectedScreenSize()
función getSelectedScreenSize()
. y la función getSelectedScreenSize()
está esperando que la segunda ventana creada por screenSelectorUI()
sea invisible. screenSelectorUI()
crea una segunda ventana, pero configura el color de esta manera:
sizeSelectorWindow.setBackground( new Color(0, 0, 0, 0) );
si miras el constructor de color javadocs:
public Color(int r, int g, int b, int a)
Crea un color sRGB con los valores rojos, verdes, azules y alfa especificados en el rango (0 - 255).
Parámetros:
- r - el componente rojo
- g - el componente verde
- b - el componente azul
- a - el componente alfa
establece el valor alfa en 0, lo que lo hace completamente invisible. (el valor alfa es transparencia) también, esta segunda ventana no está decorada y no se cierra al cerrar, por lo que ni siquiera sabe que está allí.
lo que no entiendo es cómo test1 funcionó en absoluto. nota al margen: cuando intento la prueba 1 en Mac, solo muestra el botón y todo lo que puedo hacer es hacer clic en él. el botón desaparecerá, pero la aplicación seguirá ejecutándose.
Esto es básicamente una suposición total, pero muchos de los componentes de swing hacen solicitudes al sistema operativo, no a comandos. algo así como decir: "¿puedo cambiar el tamaño a 400, 400?" el sistema operativo no tiene que hacer técnicamente lo que dices. y estaba leyendo ¿Cómo maneja Java el multihilo? que dice que el multihilo realmente depende del sistema operativo. Tengo la sensación de que se screenSelectorUI()
cuando se llama a screenSelectorUI()
por sí mismo, pero de alguna manera lo hace bien cuando está dentro del hilo de algún botón.