我有2节课。两个实现都可以运行以创建GUI。第一个是主要的,第二个是次要的。
我希望在主类的actionlistener中启动辅助类。
这是代码(两个类是分开的文件):
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);
}
}
我想将代码保存在两个文件中,我不想将这两个类混合在一个文件中。 从代码中可以看出,在Secondary类中,在它的构造函数中,我创建了一个Secondary类的实例,并运行了gui,这样当在Main类中创建此类的实例时,运行gui。
不幸的是,这种技术无效。
有什么想法吗? 感谢
答案 0 :(得分:2)
以下行是完全错误的:
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 );
}
答案 1 :(得分:2)
我建议你完全重新设计你的程序。我发现将GUI设置为创建JPanels是最有帮助的,而不是像JFrame这样的顶级窗口,然后可以将其置于JFrames或JDialogs,或JTabbedPanes中,或者在需要时通过CardLayouts交换。我发现这大大增加了我的GUI编码的灵活性,正是我建议你做的。所以......
例如,
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“视图”,但不管怎样,您都希望避免显示两个JFrame。请查看The Use of Multiple JFrames, Good/Bad Practice?。