当前位置: 首页 > 知识库问答 >
问题:

Java Swing:使用或不使用JTable创建优美的Jscrollpane

严柏
2023-03-14

我需要一个UI来一遍又一遍地收集类似的数据,这可以最好地描述为一个批处理入口。为了输入批处理,我需要一个滚动窗格来调整用户输入的数据大小。为了顺利完成此操作,我依赖于附加到jscrollpane的jtable,而行是JPanel。我在这个解决方案上遇到了一些麻烦,那就是

  1. 我不知道如何访问JPanel中的文本字段
  2. 我不知道如何在我的JTable上添加更多的jpanels作为行。

我可以补充一句,我跳到这个解决方案(它可能不一定是最好的)是在一次又一次地尝试向一个jscrollpane中添加多个jpanel,但这没有很好地工作。这个替代方案失败了,因为似乎通过setviewportview添加一个jpanel并不是为了接受一个新的面板来扩展视图而设计的。同样的一个变种是将一个jpanel附加到一个scrollpane上,然后在连接到scrollpane的mainpanel上添加许多jpanel,但视图没有展开,而scrollpane保持不变。我已经查看了Oracle的scrollpane教程,并看到了客户端的动态变化以及如何重新验证客户端,但不确定这将如何应用于我正在添加新jpanels的情况(除非我将它们添加到一个jpanel上,在添加新jpanel时,我一直在设置新客户端的首选大小)

注意:

  1. 我不断添加的jpanel并不是真的新的,因为我正在迭代它。
  2. 我尝试过的另一个第三种解决方案是使用灵活的gridlayout,它的行是用户可以选择的变量“x”,并且可以添加许多“x”jpanels。问题是,这是主要的问题,滚动窗格不允许扩展,所以也没有调整到新视图。
  3. 注意,我需要的scrollpane不应附加到JFrame,而应附加到JFrame中的内部视图(就像borderLayout UI中仅用于North或Center的scrollpane)。
  4. 我知道作为行的jpanel可以被普通行替换,其中行上的每个单元格可以充当jtextfield、jlabel或我需要的任何组件,但采用这种方法是为了使JTable看起来像实际的物理文档。

我如何做一个好的scrollpane动态扩展到jpanels的添加?

下面的代码显示了两次添加jpanels的尝试,希望扩展scrollpane,但都失败了。

解决方案一将每个单元格呈现为一个jpanel,但我无法访问jpanel上的textfield,因此我无法从用户那里获取数据,也无法添加另一行来创建批处理。

    public class JTablePanelRow extends JFrame implements ActionListener{

    JButton addRow = new JButton("Add Row");
    JTable table = new JTable();
    JScrollPane spane = new JScrollPane();
    JPanel mainPanel = new JPanel(new BorderLayout());
    JPanel panelRow = new JPanel();
    JLabel lblName = new JLabel("NAME");
    JTextField txName = new JTextField();
    JLabel lblAge = new JLabel("AGE");
    JTextField txAge = new JTextField();
    TblModel tblmodel = new TblModel();

     public static void main(String[] args) {

     JTablePanelRow tblPane = new JTablePanelRow();
     tblPane.init();

     }

    void init(){
        panelRow.setLayout(new GridLayout(2,2,4,4));
        panelRow.add(lblName);
        panelRow.add(txName);
        panelRow.add(lblAge);
        panelRow.add(txAge); 
        table.setModel(tblmodel);
        table.setRowHeight(50);
        table.getColumn("A").setCellRenderer(new     PanelRenderer(panelRow));
        spane.setViewportView(table);
        addRow.addActionListener(this);
        mainPanel.add(addRow,"North");
        mainPanel.add(spane,"Center");
        this.getContentPane().add(mainPanel);
        this.setVisible(true);
        this.setSize(new Dimension(400,500));
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource()==addRow){
            tblmodel.addNewRow();

        }
      }
    }


    class TblModel extends AbstractTableModel{


        @Override
        public int getRowCount() {
        return 1;
        }

        @Override
        public int getColumnCount() {
        return 1;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
        return "";
        }

        public void addNewRow(){
               //how to add the jpanel again
        } 

       }

       class PanelRenderer extends DefaultTableCellRenderer{
       JPanel entryPn = new JPanel();

       public PanelRenderer(JPanel entryPn){
       this.entryPn = entryPn;

       }

       @Override
       public Component getTableCellRendererComponent(JTable table, Object value,
  boolean isSelected, boolean hasFocus, int row, int column) {

       entryPn.setPreferredSize(new Dimension(200,50));
       entryPn.setBackground(Color.pink);

       return entryPn;}

          }

解决方案二尝试通过灵活的gridlayout添加jpanels,但jpanels没有添加或不可滚动。

public class GridLayoutTrick extends JFrame{

  JPanel mainPanel = new JPanel(new BorderLayout());
  JScrollPane scroll = new JScrollPane();
  JPanel entryPanel = new JPanel();
  JPanel rowPanel = new JPanel();
  int batchNumber = 10;
  JPanel northPanel = new JPanel();


 public static void main(String[] args) {
     GridLayoutTrick glt = new GridLayoutTrick();
     glt.init();
  }

  void init(){
      rowPanel.setBackground(Color.PINK);
      rowPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK,5));
      rowPanel.setPreferredSize(new Dimension(100,50));
      entryPanel.setLayout(new GridLayout(batchNumber,1,4,4));
          for(int i = 0;i < batchNumber;i++){
              entryPanel.add(rowPanel);
          }

      entryPanel.setBackground(Color.BLUE);
      scroll.setViewportView(entryPanel);
      mainPanel.add(northPanel,"North");
      mainPanel.add(scroll,"Center");
      this.getContentPane().add(mainPanel);
      this.setVisible(true);
      this.setSize(new Dimension(400,400));
      this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      } 
    }

共有2个答案

后源
2023-03-14

让我挠头的是,为什么您不单独使用JTable的可编辑功能,而是尝试使用JPanel作为单元格呈现器/编辑器,这会使您自己的生活更加困难

您应该从仔细研究如何使用表开始,以便更好地理解表的使用方式

下面是一个过于简化的示例,它允许您添加任意数量的行,并编辑表中每个单元格的值...

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {
        private DefaultTableModel model;

        public TestPane() {
            setLayout(new BorderLayout());
            model = new DefaultTableModel(new Object[]{"Name", "Age"}, 0);
            JTable table = new JTable(model);

            add(new JScrollPane(table));

            JButton btn = new JButton("Add");
            add(btn, BorderLayout.SOUTH);

            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    model.addRow(new Object[] {"", ""});
                    table.editCellAt(model.getRowCount() - 1, 0);
                    table.getEditorComponent().requestFocusInWindow();
                }
            });
        }

    }

}

就我个人而言,我会设置一个容器对象来保存数据,并通过自定义的TableModel来管理数据,但这是我自己。

我还将研究如何实现一个连续编辑模型,以允许用户在“连续”编辑模式下轻松地在表中移动

马绪
2023-03-14

解决方案二尝试通过灵活的gridlayout添加jpanels,但jpanels没有添加或不可滚动。

      for(int i = 0;i < batchNumber;i++){
          entryPanel.add(rowPanel);
      }

您只有1个“RowPanel”。

每次要将“RowPanel”添加到“EntryPanel”中时,都需要创建一个单独的“RowPanel”实例。

  mainPanel.add(northPanel,"North");
  mainPanel.add(scroll,"Center");

不要使用魔法常数。使用API中的字段:

  1. borderlayout.page_start
  2. BorderLayout.Center

虽然我真的认为MadProgrammer的建议是一个更好的解决方案。

 类似资料:
  • 我很好奇,在放置组件时,如何使用miglaway在网格上均匀分布组件: 例如,如果我在一个按钮组中放置四个JRadioButton以跨越3行2列(2,3),然后放置三个JButton,则分布的权重是不相等的,我最终会得到以下结果: 如图所示,A和B的大小相同,C保留剩余的空间:我希望A、B、C在垂直方向上等于三分之一。 如果这在GridBagLayout中是可能的,我也可以利用它,但是我在任何一种

  • 我对这个很陌生,所以也许有什么我错过了,或者只是不知道。

  • 我们有一个用dropwizard编写的RestAPI。API的一个功能是创建表单的事件三元组: userID-action-itemID如果还没有这个userID/itemID组合的操作,我们将创建一个新事件。相应的资源函数具有@UnitOfWork注释: 如果这是此特定userID或itemID的第一个事件,我们将分别创建一个用户或一个项。这是项目的功能(用户相同): 问题是我们有重复的项(即,

  • 那行代码给了我一个错误,它给了我... 线程中的异常"AWT-EventQuue-0"java.lang.ClassCast异常:javax.swing.JTable1美元不能转换为javax.swing.table.默认表模型 我该怎么解决?我需要从表中删除一行。 这是我实例化tabla_proveedor的地方

  • 问题内容: 我想创建一个可以与参数一起使用的Python装饰器: 或不使用它们(例如,默认情况下将输出重定向到stderr): 那有可能吗? 请注意,我并不是在寻找重定向输出问题的其他解决方案,这只是我想要实现的语法的一个示例。 问题答案: 我知道这个问题很旧,但是有些评论是新的,尽管所有可行的解决方案本质上都是相同的,但大多数解决方案都不是很干净也不易于阅读。 就像thobe的回答所说,处理这两

  • 我已经阅读了Node.js的文档,除非我遗漏了什么,否则它不会告诉某些操作中的参数包含什么,特别是。正如您在文档中看到的,这并不是很多。 其次,Node.js是否有完整的或至少更详细的文档,其中包含关于错误对象包含什么、参数表示什么等细节。