为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 Swing 中制作合适的 Table 以及使用合适的布局将所有元素放在各自的位置?

如何在 Swing 中制作合适的 Table 以及使用合适的布局将所有元素放在各自的位置?

青春有我 2023-06-04 17:11:53
我正在研究网络爬虫并分几个阶段实施。此阶段获取网站上提到的所有链接,并在 JTable 中显示带有标题的网页的有效链接。但是,我希望在我在要解析的 TextField 中输入 URL 之前该表已经存在(这是此分配的要求)。另外,有没有办法修复当前布局(Macintosh 窗口的第一张图片) 当前 Swing 窗口 ,以便我可以在指定位置正确显示所有 JFrame 元素,如下图所示:所有元素所在的所需摆动窗口我曾尝试使用空布局来解决布局问题,这只会让任务变成一场噩梦,而且表格会在我眼前消失。在我开始输入链接之前,我找不到让表格存在的方法。当我运行作业测试工具给出的测试时,它显示“找不到合适的表元素”。发生这种情况是因为它甚至需要在将测试用例 URL 输入文本字段进行解析之前检测活动表。
查看完整描述

2 回答

?
浮云间

TA贡献1829条经验 获得超4个赞

不要在JButton的ActionPerformed事件中创建JScrollPane和JTable。但是,如果您愿意,可以从该事件重新启用 JTable,并将链接应用到 JTable 的模型。


如果可以,请在单独的类中创建您的表单。这清理了很多东西,因为它使表单代码杂乱无章,远离手头的主要任务……页面抓取链接。表单类可能如下所示:


package webcrawler;


public class Form extends javax.swing.JFrame {


private static final long serialVersionUID = 101101L;


// Member Variables for Form Components 

public javax.swing.JTextField urlText;

public javax.swing.JButton extract;

public javax.swing.JLabel title;

public javax.swing.JTable table;


private javax.swing.JLabel jLabel1;

private javax.swing.JPanel jPanel1;

private javax.swing.JPanel jPanel2;

private javax.swing.JScrollPane scrollPane;

private javax.swing.JLabel titleLabel;


public Form() {

    initializeFormComponents();

    setLookAndFeel();

    openForm();

}


private void setLookAndFeel() {

    /* Set the Nimbus look and feel if you have it 

       or even like it. Use whatever you like   */

    try {

        for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {

            if ("Nimbus".equals(info.getName())) {

                javax.swing.UIManager.setLookAndFeel(info.getClassName());

                break;

            }

        }

    }

    catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {

        System.out.println(ex.getMessage());

    }

}


private void openForm() {

    /* Create and display the form */

    java.awt.EventQueue.invokeLater(new Runnable() {

        @Override

        public void run() {

            setVisible(true);

            setLocationRelativeTo(null);

        }

    });

}


private void initializeFormComponents() {

    jPanel1 = new javax.swing.JPanel();

    jLabel1 = new javax.swing.JLabel();

    urlText = new javax.swing.JTextField();

    extract = new javax.swing.JButton();

    jPanel2 = new javax.swing.JPanel();

    scrollPane = new javax.swing.JScrollPane();

    table = new javax.swing.JTable();

    titleLabel = new javax.swing.JLabel();

    title = new javax.swing.JLabel();


    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

    setTitle("Web Crawler");

    setAlwaysOnTop(true);


    jLabel1.setFont(new java.awt.Font("sansserif", 1, 12)); // NOI18N

    jLabel1.setText("URL:");

    urlText.setName("UrlTextField"); // NOI18N

    extract.setText("Parse");

    extract.setName("RunButton"); // NOI18N


    javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);

    jPanel1.setLayout(jPanel1Layout);

    jPanel1Layout.setHorizontalGroup(

            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

                    .addGroup(jPanel1Layout.createSequentialGroup()

                            .addContainerGap()

                            .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)

                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

                            .addComponent(urlText, javax.swing.GroupLayout.PREFERRED_SIZE, 667, javax.swing.GroupLayout.PREFERRED_SIZE)

                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

                            .addComponent(extract, javax.swing.GroupLayout.DEFAULT_SIZE, 84, Short.MAX_VALUE)

                            .addContainerGap())

    );

    jPanel1Layout.setVerticalGroup(

            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

                    .addGroup(jPanel1Layout.createSequentialGroup()

                            .addContainerGap()

                            .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)

                                    .addComponent(jLabel1)

                                    .addComponent(urlText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)

                                    .addComponent(extract))

                            .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))

    );


    table.setModel(new javax.swing.table.DefaultTableModel(

            new Object[][]{

                {null, null},

                {null, null},

                {null, null},

                {null, null}

            },

            new String[]{

                "URL", "TITLE"

            }

    ) {

        private static final long serialVersionUID = 101110L;

        Class[] types = new Class[]{

            java.lang.String.class, java.lang.String.class

        };

        boolean[] canEdit = new boolean[]{

            false, false

        };


        @Override

        public Class getColumnClass(int columnIndex) {

            return types[columnIndex];

        }


        @Override

        public boolean isCellEditable(int rowIndex, int columnIndex) {

            return canEdit[columnIndex];

        }

    });

    table.setName("TitlesTable");

    table.setEnabled(false);

    table.setGridColor(new java.awt.Color(198,195,195));

    table.setInheritsPopupMenu(true);

    table.setRowHeight(20);

    table.setShowHorizontalLines(true);

    table.setShowVerticalLines(true);

    scrollPane.setViewportView(table);


    titleLabel.setFont(new java.awt.Font("sansserif", 1, 12));

    titleLabel.setText("Title:");


    title.setFont(new java.awt.Font("sansserif", 1, 12));

    title.setText("None");

    title.setName("TitleLabel");


    javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);

    jPanel2.setLayout(jPanel2Layout);

    jPanel2Layout.setHorizontalGroup(

            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

                    .addGroup(jPanel2Layout.createSequentialGroup()

                            .addContainerGap()

                            .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

                                    .addComponent(scrollPane)

                                    .addGroup(jPanel2Layout.createSequentialGroup()

                                            .addComponent(titleLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE)

                                            .addGap(18, 18, 18)

                                            .addComponent(title, javax.swing.GroupLayout.PREFERRED_SIZE, 348, javax.swing.GroupLayout.PREFERRED_SIZE)

                                            .addGap(0, 0, Short.MAX_VALUE)))

                            .addContainerGap())

    );

    jPanel2Layout.setVerticalGroup(

            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()

                            .addContainerGap()

                            .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)

                                    .addComponent(titleLabel)

                                    .addComponent(title))

                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)

                            .addComponent(scrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 478, javax.swing.GroupLayout.PREFERRED_SIZE)

                            .addContainerGap())

    );


    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());

    getContentPane().setLayout(layout);

    layout.setHorizontalGroup(

            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

                    .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)

                    .addComponent(jPanel2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)

    );

    layout.setVerticalGroup(

            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

                    .addGroup(layout.createSequentialGroup()

                            .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)

                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)

                            .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))

    );

        pack();

    }

}

然后您的 WebCrawler 类可能如下所示:


package webcrawler;


import javax.swing.*;

import javax.swing.table.DefaultTableModel;

import javax.swing.table.TableModel;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.io.BufferedReader;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.net.URL;

import java.nio.charset.StandardCharsets;

import java.util.Iterator;

import java.util.Map;

import java.util.SortedMap;

import java.util.TreeMap;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

import javax.swing.table.JTableHeader;

import javax.swing.table.TableCellRenderer;



public class WebCrawler {


private static final long serialVersionUID = 101011L;

private Form form;

String LINE_SEPARATOR = System.getProperty("line.separator");


public static void main(String[] args) {

    // To eliminate the need for statics. I Don't want it right now. 

    new WebCrawler().startApp(args);

}


private void startApp(String[] args) {

    form = new Form();

    form.extract.addActionListener(new ActionListener() {

        @Override

        public void actionPerformed(ActionEvent e) {

            try {

                clearJTable();  // Clear the JTable

                String url = form.urlText.getText();

                /* Get url from JTextField */

                url = url.replaceAll("^\"+ \"+$", "");


                final InputStream inputStream = new URL(url).openStream();

                final BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));

                final StringBuilder stringBuilder = new StringBuilder();


                String nextLine;

                while ((nextLine = reader.readLine()) != null) {

                    stringBuilder.append(nextLine);

                    stringBuilder.append(LINE_SEPARATOR);

                }


                final String siteText = stringBuilder.toString();


                Pattern pattern = Pattern.compile("<title>(.+?)</title>", Pattern.CASE_INSENSITIVE);

                Matcher matcher = pattern.matcher(siteText);


                String titleString = matcher.find() ? matcher.group(1) : "null";

                form.title.setText(titleString);


                SortedMap<String, String> links = new TreeMap<>();


                Pattern pTag = Pattern.compile("(?i)<a([^>]+)>(.+?)</a>", Pattern.CASE_INSENSITIVE);

                Pattern pLink = Pattern.compile("\\s*(?i)href\\s*=\\s*(\"([^\"]*\")|'[^']*'|([^'\">\\s]+))", Pattern.CASE_INSENSITIVE);


                Matcher mTag = pTag.matcher(siteText);


                try {

                    while (mTag.find()) {


                        String href = mTag.group(1);     // get the values of href

                        String linkElem = mTag.group(2); // get the text of link Html Element


                        Matcher mLink = pLink.matcher(href);


                        while (mLink.find()) {

                            String link = mLink.group(1);

                            link = link.substring(1, link.length() - 1);

                            pattern = Pattern.compile("http", Pattern.CASE_INSENSITIVE);

                            matcher = pattern.matcher(link);

                            if (!matcher.find()) {

                                link = String.join("", url, link);

                            }

                            try {

                                //URL urlValidator = new URL(link);

                                //if (urlValidator.getContent().equals("text/html")) {

                                links.put(link, linkElem);

                                //}

                            }

                            catch (Exception ex) {

                                System.out.println(ex);

                                //System.out.println("Exception encountered at " + link);

                            }

                        }

                    }

                    form.table.setEnabled(true);    // Enable JTable

                    form.table.setModel(toTableModel(links));

                }

                catch (Exception ex) {

                    System.out.println(ex);

                }

            }

            catch (Exception ex) {

                System.out.println(ex);

            }

            // Is there anything in the table?

            if (form.table.getModel().getRowCount() == 0) {

                // NOPE...So Disable JTable.

                form.table.setEnabled(true);

            }

        }

    });

    form.urlText.requestFocus();

}


private void clearJTable() {

    DefaultTableModel tableModel = (DefaultTableModel) form.table.getModel();

    while (tableModel.getRowCount() > 0) {

        for (int i = 0; i < tableModel.getRowCount(); i++) {

            tableModel.removeRow(i);

        }

    }

    // Reset 4 blank rows in the table for looks :) 

    form.table.setModel(new DefaultTableModel(

            new Object[][]{{null, null}, {null, null}, {null, null},{null, null}},

            new String[]{"<html><font color=blue><b>U R L</b></font></html>", 

                         "<html><font color=red><b>T I T L E</b></font></html>"}));

    // Yes...you can use basic HTML in a JTable Header.

}


public TableModel toTableModel(Map<?, ?> map) {

    DefaultTableModel model = new DefaultTableModel(

            new Object[]{"URL", "TITLE"}, 0

    );

    for (Iterator it = map.entrySet().iterator(); it.hasNext();) {

        Map.Entry entry = (Map.Entry) it.next();

        model.addRow(new Object[]{entry.getKey(), entry.getValue()});

    }

    return model;

}


}



查看完整回答
反对 回复 2023-06-04
?
蓝山帝景

TA贡献1843条经验 获得超7个赞

我希望在输入 URL 之前表格已经存在


然后,您需要在创建所有其他组件并将其添加到框架的同时创建一个空表并将其添加到框架。


您需要为 JTable 创建一个实例变量才能修改其模型。


将表格添加到框架的代码类似于:


add(title, BorderLayout.LINE_START);

DefaultTableModel model = new DefaultTableModel (new Object[] { "URL", "Title" }, 0);

table = new JTable( model );

add(new JScrollPane(table), BorderLayout.CENTER);

所以现在当您启动应用程序时,您将看到一个只有列的空表。


您的方法中的代码toTableModel(...)现在变成如下所示:


//DefaultTableModel model = new DefaultTableModel (new Object[] { "URL", "Title" }, 0);

DefaultTableModel model = (DefaultTableModel)table.getModel();

model.setRowCount(0);

这只是删除模型中的所有行,因此您的循环代码可以添加每一行新数据。


当然,您还可以删除当前创建 JTable 和 JScrollPane 的 ActionListener 中的代码,因为不再需要它。


另外,有没有办法修复当前布局


您的嵌套面板具有不同的布局管理器,以达到您想要的效果。


例如,您希望表格能够根据表格中的数据增长/缩小,因此应该将其添加到CENTER您的BorderLayout.


但是,顶部到两行是固定的,它们应该添加到子面板中。然后这个面板将被添加到PAGE_START你的BorderLayout. Maybe a verticalBoxLayout` 中。


然后每一行都是另一个子面板。第一行可以是带有水平的面板BoxLayout,第二行可以是带有FlowLayout.


查看完整回答
反对 回复 2023-06-04
  • 2 回答
  • 0 关注
  • 75 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信