运行 新 GUI window 来自另一个 class 的事件
Run new GUI window from an event of another class
我有 2 个 class。两者都实现了 运行 能够创建 GUI。第一个为主,第二个为副class.
我想在主 class 的 actionlistener 中启动辅助 class。
这是代码(两个class是分开的文件):
public class Main implements Runnable
{
private JTextField txt1, txt2;
private JLabel lbl1, lbl2;
public void run()
{
JFrame frame = new JFrame("Secondary");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container pane = frame.getContentPane();
JPanel background = new JPanel();
background.setLayout(new BoxLayout(background, BoxLayout.LINE_AXIS));
.........
// Horizontally adding the textbox and button in a Box
Box box = new Box(BoxLayout.Y_AXIS);
......
background.add(box);
pane.add(background);
frame.pack();
frame.setVisible(true);
}
private class SListener implements ActionListener
{
public void actionPerformed(ActionEvent a)
{
Secondary s = new Secondary();
}
}
public static void main (String[] args)
{
Main gui = new Main();
SwingUtilities.invokeLater(gui);
}
}
public class Secondary implements Runnable
{
private JTextField txt1, txt2;
private JLabel lbl1, lbl2;
public Secondary()
{
Secondary gui = new Secondary();
SwingUtilities.invokeLater(gui);
}
public void run()
{
JFrame frame = new JFrame("Secondary");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container pane = frame.getContentPane();
JPanel background = new JPanel();
background.setLayout(new BoxLayout(background, BoxLayout.LINE_AXIS));
.........
// Horizontally adding the textbox and button in a Box
Box box = new Box(BoxLayout.Y_AXIS);
......
background.add(box);
pane.add(background);
frame.pack();
frame.setVisible(true);
}
}
我想将代码保存在两个文件中,我不想将两个 classes 混合在一个文件中。
正如您从代码中看到的那样,在辅助 class 中,在它的构造函数中我创建了辅助 class 的实例并且我 运行 gui 以便当此 [= 的实例26=]是在Main中创建的class,到运行的gui.
不幸的是,这种技术不起作用。
有什么想法吗?
谢谢
下面一行完全错误:
public Secondary(){
Secondary gui = new Secondary();
SwingUtilities.invokeLater(gui);
}
每次你在代码中的某处调用 new Secondary()
时,上面的代码都会被触发,它依次调用 new Secondary()
一次又一次,一次又一次,......你的程序是已屏蔽。
您可能想将其替换为
public Secondary(){
SwingUtilities.invokeLater(this);
}
这将避免循环,但这对于构造函数来说是一种奇怪的行为。
切换到空构造函数(或将其全部删除)更有意义
public Secondary(){
}
并将您的侦听器重写为
public void actionPerformed(ActionEvent a){
Secondary s = new Secondary();
SwingUtilities.invokeLater( s );
}
我建议您完全重新设计您的程序。我发现将我的 GUI 用于创建 JPanel 而非顶级 windows(例如 JFrame)最有帮助,然后可以将其放置到 JFrames 或 JDialogs 或 JTabbedPanes 中,或通过 CardLayouts 在任何需要的地方进行交换。我发现这极大地增加了我的 GUI 编码的灵活性,这正是我建议您做的。所以...
- 您的第一个 class 创建一个 JPanel,然后将其放入 JFrame。
- 在第一个 class 的 ActionListener 中,创建第二个 class 的实例,将其放入 JDialog(而不是 JFrame)中,然后显示它。
例如,
import java.awt.Component;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class TwoWindowEg {
public TwoWindowEg() {
// TODO Auto-generated constructor stub
}
private static void createAndShowGui() {
GuiPanel1 mainPanel = new GuiPanel1();
JFrame frame = new JFrame("Main GUI");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class GuiPanel1 extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 650;
private GuiPanel2 guiPanel2 = new GuiPanel2(); // our second class!
private JDialog dialog = null; // our JDialog
public GuiPanel1() {
setBorder(BorderFactory.createTitledBorder("GUI Panel 1"));
add(new JButton(new LaunchNewWindowAction("Launch New Window")));
add(new JButton(new DisposeAction("Exit", KeyEvent.VK_X)));
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class LaunchNewWindowAction extends AbstractAction {
public LaunchNewWindowAction(String name) {
super(name);
}
@Override
public void actionPerformed(ActionEvent e) {
if (dialog == null) {
// get the Window that holds this JPanel
Window win = SwingUtilities.getWindowAncestor(GuiPanel1.this);
dialog = new JDialog(win, "Second Window", ModalityType.APPLICATION_MODAL);
dialog.add(guiPanel2);
dialog.pack();
}
dialog.setVisible(true);
}
}
}
class GuiPanel2 extends JPanel {
public GuiPanel2() {
setBorder(BorderFactory.createTitledBorder("GUI Panel 1"));
add(new JLabel("The second JPanel/Class"));
add(new JButton(new DisposeAction("Exit", KeyEvent.VK_X)));
}
}
class DisposeAction extends AbstractAction {
public DisposeAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
Component comp = (Component) e.getSource();
Window win = SwingUtilities.getWindowAncestor(comp);
win.dispose();
}
}
或者,您可以使用 CardLayout 交换 JPanel "views",但无论哪种方式,您都希望避免显示两个 JFrame。请看一下 The Use of Multiple JFrames, Good/Bad Practice?.
我有 2 个 class。两者都实现了 运行 能够创建 GUI。第一个为主,第二个为副class.
我想在主 class 的 actionlistener 中启动辅助 class。
这是代码(两个class是分开的文件):
public class Main implements Runnable
{
private JTextField txt1, txt2;
private JLabel lbl1, lbl2;
public void run()
{
JFrame frame = new JFrame("Secondary");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container pane = frame.getContentPane();
JPanel background = new JPanel();
background.setLayout(new BoxLayout(background, BoxLayout.LINE_AXIS));
.........
// Horizontally adding the textbox and button in a Box
Box box = new Box(BoxLayout.Y_AXIS);
......
background.add(box);
pane.add(background);
frame.pack();
frame.setVisible(true);
}
private class SListener implements ActionListener
{
public void actionPerformed(ActionEvent a)
{
Secondary s = new Secondary();
}
}
public static void main (String[] args)
{
Main gui = new Main();
SwingUtilities.invokeLater(gui);
}
}
public class Secondary implements Runnable
{
private JTextField txt1, txt2;
private JLabel lbl1, lbl2;
public Secondary()
{
Secondary gui = new Secondary();
SwingUtilities.invokeLater(gui);
}
public void run()
{
JFrame frame = new JFrame("Secondary");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container pane = frame.getContentPane();
JPanel background = new JPanel();
background.setLayout(new BoxLayout(background, BoxLayout.LINE_AXIS));
.........
// Horizontally adding the textbox and button in a Box
Box box = new Box(BoxLayout.Y_AXIS);
......
background.add(box);
pane.add(background);
frame.pack();
frame.setVisible(true);
}
}
我想将代码保存在两个文件中,我不想将两个 classes 混合在一个文件中。 正如您从代码中看到的那样,在辅助 class 中,在它的构造函数中我创建了辅助 class 的实例并且我 运行 gui 以便当此 [= 的实例26=]是在Main中创建的class,到运行的gui.
不幸的是,这种技术不起作用。
有什么想法吗? 谢谢
下面一行完全错误:
public Secondary(){
Secondary gui = new Secondary();
SwingUtilities.invokeLater(gui);
}
每次你在代码中的某处调用 new Secondary()
时,上面的代码都会被触发,它依次调用 new Secondary()
一次又一次,一次又一次,......你的程序是已屏蔽。
您可能想将其替换为
public Secondary(){
SwingUtilities.invokeLater(this);
}
这将避免循环,但这对于构造函数来说是一种奇怪的行为。
切换到空构造函数(或将其全部删除)更有意义
public Secondary(){
}
并将您的侦听器重写为
public void actionPerformed(ActionEvent a){
Secondary s = new Secondary();
SwingUtilities.invokeLater( s );
}
我建议您完全重新设计您的程序。我发现将我的 GUI 用于创建 JPanel 而非顶级 windows(例如 JFrame)最有帮助,然后可以将其放置到 JFrames 或 JDialogs 或 JTabbedPanes 中,或通过 CardLayouts 在任何需要的地方进行交换。我发现这极大地增加了我的 GUI 编码的灵活性,这正是我建议您做的。所以...
- 您的第一个 class 创建一个 JPanel,然后将其放入 JFrame。
- 在第一个 class 的 ActionListener 中,创建第二个 class 的实例,将其放入 JDialog(而不是 JFrame)中,然后显示它。
例如,
import java.awt.Component;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class TwoWindowEg {
public TwoWindowEg() {
// TODO Auto-generated constructor stub
}
private static void createAndShowGui() {
GuiPanel1 mainPanel = new GuiPanel1();
JFrame frame = new JFrame("Main GUI");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class GuiPanel1 extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 650;
private GuiPanel2 guiPanel2 = new GuiPanel2(); // our second class!
private JDialog dialog = null; // our JDialog
public GuiPanel1() {
setBorder(BorderFactory.createTitledBorder("GUI Panel 1"));
add(new JButton(new LaunchNewWindowAction("Launch New Window")));
add(new JButton(new DisposeAction("Exit", KeyEvent.VK_X)));
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class LaunchNewWindowAction extends AbstractAction {
public LaunchNewWindowAction(String name) {
super(name);
}
@Override
public void actionPerformed(ActionEvent e) {
if (dialog == null) {
// get the Window that holds this JPanel
Window win = SwingUtilities.getWindowAncestor(GuiPanel1.this);
dialog = new JDialog(win, "Second Window", ModalityType.APPLICATION_MODAL);
dialog.add(guiPanel2);
dialog.pack();
}
dialog.setVisible(true);
}
}
}
class GuiPanel2 extends JPanel {
public GuiPanel2() {
setBorder(BorderFactory.createTitledBorder("GUI Panel 1"));
add(new JLabel("The second JPanel/Class"));
add(new JButton(new DisposeAction("Exit", KeyEvent.VK_X)));
}
}
class DisposeAction extends AbstractAction {
public DisposeAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
Component comp = (Component) e.getSource();
Window win = SwingUtilities.getWindowAncestor(comp);
win.dispose();
}
}
或者,您可以使用 CardLayout 交换 JPanel "views",但无论哪种方式,您都希望避免显示两个 JFrame。请看一下 The Use of Multiple JFrames, Good/Bad Practice?.