通过按钮按下打开另一个类作为显示面板

时间:2015-05-01 04:28:49

标签: java swing class dialog

基本上我正试图通过主程序中的按钮来打开我的porttest.java类。

我认为他们可能是通过frame.add(porttest)来实现它的方法,但这不起作用。

这是我的porttest.java代码。

package Random;
import gnu.io.*;
import java.awt.Color;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.TooManyListenersException;

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JLabel;

import java.awt.BorderLayout;
import java.util.Enumeration;
import java.util.HashMap;

import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JPanel;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.JComboBox;


public class porttest {
    private Enumeration ports = null;
    private HashMap portMap = new HashMap();
    private JFrame frame;
    private JPanel panel;
    private JLabel label;
    private JComboBox comboBox;
    public porttest() {
        initialize();
        searchForPorts();
    }
      public void searchForPorts()
        {
            ports = CommPortIdentifier.getPortIdentifiers();

            while (ports.hasMoreElements())
            {
                CommPortIdentifier curPort = (CommPortIdentifier)ports.nextElement();

                //get only serial ports
                if (curPort.getPortType() == CommPortIdentifier.PORT_SERIAL)
                {
                    comboBox.addItem(curPort.getName());
                    portMap.put(curPort.getName(), curPort);
                }
            }
        }
    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(null);

        panel = new JPanel();
        panel.setBounds(0, 0, 442, 266);
        panel.setLayout(null);

        label = new JLabel("COM Ports:");
        label.setBounds(10, 130, 82, 14);
        panel.add(label);
        frame.getContentPane().add(panel);

        comboBox = new JComboBox();
        comboBox.setBounds(76, 124, 93, 26);
        panel.add(comboBox);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    porttest window = new porttest();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

我是否需要在此处添加一些代码才能使其正常工作?

我想要它做的就是在我的主程序中间打开,这样用户可以设置一些设置然后关闭程序。我这样做的唯一原因是因为我似乎无法让JComboBox在Jmenu中工作。

也许是他们用JComboBox打开对话框的另一种方式?

任何帮助都会很棒。

2 个答案:

答案 0 :(得分:2)

你说:

  

我认为他们可能是通过frame.add(porttest)来实现它的方法,但这不起作用。

或者更确切地说:

frame.add(new PortTest());

你知道为什么吗?因此,porttest不会扩展任何组件或具有可以这种方式使用的组件字段。我将建议您将GUI类设置为创建JPanels,然后可以将其放入JFrames或JDialogs,或JTabbedPanes,或者在需要时通过CardLayouts交换。这将大大提高GUI编码的灵活性。

其他建议:

  • 避免null布局和setBounds(...)。虽然null布局和setBounds()似乎是Swing新手,比如创建复杂GUI的最简单和最好的方法,但是你创建的Swing GUI越多,在使用它们时会遇到更严重的困难。当GUI调整大小时,它们不会调整组件的大小,它们是增强或维护的皇室女巫,当它们被放置在滚动窗格中时它们完全失败,当它们在所有平台上观看时或者与原始平台不同的屏幕分辨率时它们看起来很糟糕
  • 相反,您最好不要学习和使用布局管理器。您可以在此处找到布局管理器教程:Layout Manager Tutorial,您可以在此处找到指向Swing教程和其他Swing资源的链接:Swing Info
  • 为了帮助我们并在将来帮助自己,请编辑代码并更改变量名称以符合Java命名约定:类名称都以大写字母开头,方法/变量名称以较低的字母开头案件信。

答案 1 :(得分:2)

这是一个典型的例子,将所有鸡蛋放入一个篮子里,然后想知道为什么你最终会得到一个omlet。

Java是OO语言,您应该将您的类分解为责任区,通过图层构建功能,这为您提供了灵活性和根据需要更改图层的能力。

例如。您的ports班级应该只完成一份工作和一份工作,获取CommPortIdentifier的列表

  public class Ports {

    public static List<CommPortIdentifier> listCommPorts() {
      List<CommPortIdentifier> listOfPorts = new ArrayList<>(25);
      Enumeration ports = CommPortIdentifier.getPortIdentifiers();

      while (ports.hasMoreElements()) {
        CommPortIdentifier curPort = (CommPortIdentifier) ports.nextElement();

        //get only serial ports
        if (curPort.getPortType() == CommPortIdentifier.PORT_SERIAL) {
          listOfPorts.add(curPort);
        }
      }
      return listOfPorts;
    }

  }

然后,您需要一些方法来加载这些端口并显示。没有你正在使用的库,我假设最坏的并且假设这个方法需要时间来运行(或者可能阻塞),所以我使用SwingWorker来实际加载......

  public class LoadPortsWorker extends SwingWorker<List<CommPortIdentifier>, Object> {

    @Override
    protected List<CommPortIdentifier> doInBackground() throws Exception {
      return Ports.listCommPorts();
    }

  }

接下来,我们需要一些方法来显示它们。是的,您可以使用JComboBox,但您还提到要使用菜单项...

    JMenu menu = new JMenu("Ports");
    LoadPortsWorker worker = new LoadPortsWorker();
    worker.addPropertyChangeListener(new PropertyChangeListener() {
      @Override
      public void propertyChange(PropertyChangeEvent evt) {
        LoadPortsWorker worker = (LoadPortsWorker)evt.getSource();
        switch (evt.getPropertyName()) {
          case "state":
            switch (worker.getState()) {
              case DONE:
                try {
                  List<CommPortIdentifier> ports = worker.get();
                  ButtonGroup bg = new ButtonGroup();
                  for (CommPortIdentifier port : ports) {
                    JRadioButtonMenuItem mi = new JRadioButtonMenuItem(new PortAction(port));
                    bg.add(mi);
                    menu.add(mi);
                  }
                } catch (InterruptedException | ExecutionException exp) {
                  exp.printStackTrace();
                }
                break;
            }
        }
      }
    });
    worker.execute();

    JMenuBar mb = new JMenuBar();
    mb.add(menu);

    JFrame frame = new JFrame("Testing");
    frame.setJMenuBar(mb);

这使得JMenu称为“端口”,它会创建一系列JRadioButtonMenuItem个,每个端口一个,并将它们添加到“端口”菜单。每个端口菜单项都添加到同一个按钮组,这意味着只能选择一个。

为了让生活更轻松,我使用ActionCommPortIdentifier打包成一个漂亮的简单包...

  public class PortAction extends AbstractAction {

    private CommPortIdentifier port;

    public PortAction(CommPortIdentifier port) {
      this.port = port;
      putValue(SELECTED_KEY, false);
      putValue(NAME, port.getName());
    }

    @Override
    public void actionPerformed(ActionEvent e) {
      // Do what ever you want to do with the port...
    }

  }

在此示例中,我将“端口”菜单直接添加到JMenuBar,但您可以轻松地将其添加到另一个JMenu并创建子菜单。

此外,使用此基本概念,您还可以填充ComboBoxModelListModel甚至TableModel ...

查看How to use menusHow to use actionsWorker threads and SwingWorker了解详情