当前位置: 首页 > news >正文

swing笔记

swing

JFrame

jframe是一个顶层容器

创建jframe并设置标题为Swing
JFrame frame = new JFrame("Swing");
显示JFrame
frame.setVisible(true);
退出swing应用
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
退出的四个常数
  • JFrame.DO_NOTHING_ON_CLOSE: 表示窗口关闭时不执行任何操作。通常用于自定义关闭逻辑,例如显示确认对话框后再决定是否关闭窗口。
  • JFrame.HIDE_ON_CLOSE: 表示窗口关闭时隐藏窗口而不终止应用程序。这个选项适用于需要隐藏窗口而不完全退出应用程序的情况。
  • JFrame.DISPOSE_ON_CLOSE: 表示窗口关闭时释放窗口占用的所有资源,并终止应用程序。这是通常的默认行为,适用于大多数独立应用程序。
  • JFrame.EXIT_ON_CLOSE: 表示窗口关闭时终止应用程序。这个选项会导致 System.exit() 被调用,完全退出 Java 虚拟机。
JFrame的大小设置
frame.setSize(int width,int height);
JFrame的位置设置
frame.setLocation(int x,int y);
同时设置位置和大小
frame.setBounds(int x,int y,int widht,int height);
添加组件

要将JFrame放在屏幕中央,使用null参数调用其setLocationRelativeTo()方法

当向JFrame添加UI控件时,需要将其添加到JFrame的内容窗格

获取内容窗格的引用及添加

Container contentPane = frame.getContentPane();
contentPane.add(aComponent); //aComponent为UI组件

添加一个按钮Close

frame.getContentPane().add(new JButton("Close"));
包JFrame

JFrame的pack()方法检查JFrame上的所有组件,并决定它们的首选大小,并设置JFrame的大小刚好足以显示所有组件

当我们调用pack()方法时,我们不需要设置JFrame的大小,pack()方法将计算JFrame的大小并设置它

当使用pack()方法时,我们不需要调用setBounds()方法,要在pack()方法后定位JFrame,请使用setLocation(x,y)方法

JFrame状态

设置JFrame的状态

frame.setExtendedState(JFrame.MAXIMIZED_BOTH);

状态常量

JFrame状态常量描述
NORMALJFrame以正常大小显示。
ICONIFIEDJFrame显示为最小化状态。
MAXIMIZED_HORIZJFrame显示为水平最大化,但垂直尺寸正常。
MAXIMIZED_VERTJFrame显示为水平最大化,但垂直尺寸正常。…
MAXIMIZED_BOTHJFrame显示为水平和垂直最大化。
默认按钮

将自定义的按钮设置为默认按钮

// Create a  JButton
JButton okButton   = new JButton("OK");
// Set  okButton   as  the   default  button 
frame.getRootPane().setDefaultButton(okButton);
窗口事件

可以使用WindowListener接口和WindowAdapter类

	JFrame frame = new JFrame();frame.addWindowListener(new WindowListener() {@Overridepublic void windowOpened(WindowEvent e) {System.out.println("JFrame has  been  made visible first  time");}@Overridepublic void windowClosing(WindowEvent e) {System.out.println("JFrame is closing.");}@Overridepublic void windowClosed(WindowEvent e) {System.out.println("JFrame is closed.");}@Overridepublic void windowIconified(WindowEvent e) {System.out.println("JFrame is  minimized.");}@Overridepublic void windowDeiconified(WindowEvent e) {System.out.println("JFrame is restored.");}@Overridepublic void windowActivated(WindowEvent e) {System.out.println("JFrame is activated.");}@Overridepublic void windowDeactivated(WindowEvent e) {System.out.println("JFrame is deactivated.");}});// Use the WindowAdapter class to intercept only the window closing eventframe.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {System.out.println("JFrame is closing.");}});

dispose()方法使窗口不可见,并将资源释放到操作系统。

Swing布局管理器

容器使用布局管理器来定位其所有组件

JFrame的内容窗格的默认布局管理器时BorderLayout

JPanel的默认布局管理器是FlowLayout

可以使用setLayout()方法更改,传入null则为删除布局管理器

容器的getLayout()方法返回容器当前正在使用的布局管理器的引用

JFrame  frame  = new JFrame("Frame"); 
Container contentPane = frame.getContentPane(); 
contentPane.setLayout(new FlowLayout());
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
空布局管理器

也称为绝对定位,使用setBounds()方法设置组件的位置

Container contentPane = frame.getContentPane();
contentPane.setLayout(null);
JButton b1 = new JButton("Button");
contentPane.add(b1);
b1.setBounds(10, 10, 100, 20);
FlowLayout流式布局

FlowLayout按照添加容器的顺序布置组件水平或垂直

水平布局调用setComponentOrientation()方法来设置容器的方向

容器及其子项的方向使用applyComponentOrientation()方法

JFrame  frame  = new JFrame("Test");
Container pane  = frame.getContentPane();
pane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
JFrame  frame  = new JFrame("Test");
Container pane  = frame.getContentPane();
pane.applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);

流式布局尝试将所有组件放入一行,给他们的首选大小

如果所有组件不适合一行,则会启动另一行

流式布局可以为宽度和高度添加额外的空间

设置对齐

FlowLayout  flowLayout = new FlowLayout(FlowLayout.RIGHT);FlowLayout  flowLayout = new FlowLayout(FlowLayout.LEFT);
flowLayout.setAlignment(FlowLayout.RIGHT);

5种对齐方式

  • LEFT
  • RIGHT
  • CENTER
  • LEADING
  • TRAILING
BorderLayout边框布局

容器上的组件按照上北下南左西右东的顺序摆放

// 设置布局器为BorderLayerout
// 容器上的组件按照上北下南左西右东中的顺序摆放
f.setLayout(new BorderLayout());
JButton b1 = new JButton("aa");
JButton b2 = new JButton("bb");
JButton b3 = new JButton("cc");
JButton b4 = new JButton("dd");
JButton b5 = new JButton("ee");// 加入到容器的时候,需要指定位置
f.add(b1,BorderLayout.NORTH);
f.add(b2,BorderLayout.SOUTH);
f.add(b3,BorderLayout.EAST);
f.add(b4,BorderLayout.WEST);
f.add(b5,BorderLayout.CENTER);
GridLayout网格布局
// 设置布局器为GridLayerout,即网格布局器
// 该GridLayerout的构造方法表示该网格是2行3列
f.setLayout(new GridLayout(2,3));
JButton b1 = new JButton("aa");
JButton b2= new JButton("bb");
JButton b3 = new JButton("cc");
JButton b4 = new JButton("dd");
JButton b5 = new JButton("ee");f.add(b1);
f.add(b2);
f.add(b3);
f.add(b4);
f.add(b5);

setPreferredSize建议大小,只对部分布局有效

b3.setPreferredSize(new Dimension(180,40));
CardLayout卡片布局

卡片布局将容器分成许多层,每层的显示空间占据整个容器的大小,但是每层只允许放置一个组件

GridBagLayout网格包布局‘

网格包布局不需要组件的尺寸一致,允许组件扩展到多行多列

BoxLayout盒布局

盒布局通常和Box容器联合使用

组件

标签JLable

标签是可以包含文本和图像的非交互组件

按钮JButton
点击按钮弹出新窗口查看日志
private void jButton8ActionPerformed(java.awt.event.ActionEvent evt) {// 查看更新日志javax.swing.JFrame frame = new javax.swing.JFrame("接口数据更新日志");frame.setDefaultCloseOperation(javax.swing.JFrame.DISPOSE_ON_CLOSE);jPanel12.add(jPanel14, java.awt.BorderLayout.NORTH);JPanel jPanel = new JPanel();jPanel.setLayout(new java.awt.BorderLayout());frame.setContentPane(jPanel);javax.swing.JScrollPane js = new javax.swing.JScrollPane();js.setPreferredSize(new java.awt.Dimension(1000, 600));javax.swing.JTable table = new javax.swing.JTable();table.setModel(new javax.swing.table.DefaultTableModel(new Object[][]{},new String[]{"更新时间", "节点名称", "更新类型", "旧值", "新值"}) {boolean[] canEdit = new boolean[]{false, false, false, false, false};@Overridepublic boolean isCellEditable(int rowIndex, int columnIndex) {return canEdit[columnIndex];}});table.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));js.setViewportView(table);jPanel.add(js, java.awt.BorderLayout.CENTER);DefaultTableModel dtm = (DefaultTableModel) table.getModel();List<String[]> logList = service.qryXnyagcLog();TableOperate.setTModelData(dtm, logList);int[] cols = {0, 1, 2, 3, 4};int[] widths = {200, 200, 70, 60, 60};Column_Width.setColumnWidth(table, cols, widths);com.qctc.view.common.MyInterpro.MyInterpro(jPanel.getComponents());frame.pack();frame.setPreferredSize(new Dimension(1000, 600));frame.setVisible(true);Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();int screenWidth = screenSize.width;int screenHeight = screenSize.height;int frameWidth = frame.getSize().width;int frameHeight = frame.getSize().height;int x = (screenWidth - frameWidth) / 2;int y = (screenHeight - frameHeight) / 2;frame.setLocation(x, y);frame.setAlwaysOnTop(true);
}                    
单行文本JTextField
文本域JTextArea
复选框JCheckBox
单选按钮JRadioButton
下拉列表JComboBox
添加选择项监听事件
        qCombox1.addItemListener(new ItemListener() {@Overridepublic void itemStateChanged(ItemEvent e) {if (e.getStateChange() == ItemEvent.SELECTED) {String selectedOption = (String) qCombox1.getSelectedItem();qLabel6.setText(idMap.getOrDefault(selectedOption, ""));}}});
模拟用户点击
jRadioButton2.doClick()
列表框JList
树JTree
设置字体颜色
        DefaultTreeCellRenderer dtcr = new DefaultTreeCellRenderer();// 设置非选中字体颜色dtcr.setTextNonSelectionColor(Color.WHITE);// 设置选中字体颜色dtcr.setTextSelectionColor(Color.BLUE);dtcr.setBackgroundNonSelectionColor(Constant.C_JPANEL_BG);dtcr.setBackgroundSelectionColor(new Color(57, 105, 138));// 设置三种图标dtcr.setClosedIcon(UIManager.getIcon("Tree.closedIcon"));dtcr.setOpenIcon(UIManager.getIcon("Tree.openIcon"));dtcr.setLeafIcon(UIManager.getIcon("Tree.leafIcon"));jTree1.setCellRenderer(dtcr);
设置单选
jTree1.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
选择事件
jTree1.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {@Overridepublic void valueChanged(javax.swing.event.TreeSelectionEvent evt) {TreePath path = jTree1.getSelectionPath();if (path == null) {return;}DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) path.getLastPathComponent();Object nodeInfo = selectedNode.getUserObject();TreeNodeInfo node = (TreeNodeInfo) nodeInfo;if (!treeList.isEmpty()) {for (int i = 0; i < treeList.size(); i++) {String[] get = treeList.get(i);if (!"断面".equals(get[0])) {continue;}if (get[1].equals(node.Tree_Id)) {selectedSection = get;// System.out.println("选择的断面:" + Arrays.toString(get));jLabel2.setText(get[1]); // IDList<String[]> sectionList = service.querySectionById(get[6]);if (sectionList.isEmpty()) {jLabel12.setText(get[6]); // ID} else {String[] strs = sectionList.get(0);jLabel12.setText(strs[0]); // ID}break;}}}}
});
递归加载树的数据
    private void getTreeModel() {model = new DefaultTreeModel(null);IconTreeNode root = new IconTreeNode(new TreeNodeInfo(Constant.gsmc, "1", "root"));model.setRoot(root);createTree("1", root);}private void createTree(String pid, DefaultMutableTreeNode parentNode) {for (int i = 0; i < treeList.size(); i++) {String[] get = treeList.get(i);if (pid.equals(get[3])) {// 先判断断面是否匹配(本系统ID是否为空),再判断父断面是否匹配IconTreeNode node = new IconTreeNode(new TreeNodeInfo(get[2] + ("断面".equals(get[0]) ? ("".equals(get[6]) ? "[断面未匹配]" : (!"1".equals(get[3]) && !get[4].equals(get[9]) ? "[父断面未匹配]" : "")) : ""),get[1], "电厂".equals(get[0]) ? "unit" : "sect"));
//                System.out.println("创建树节点:"+get[1]);parentNode.add(node);createTree(get[1], node);}}}
搜索树的层级
// 定义变量
private int level;
// 归零变量,调用方法
level = 0;
searchLevel(selectedSection[1]);
// 搜索方法实现
private void searchLevel(String id) {for (int i = 0; i < treeList.size(); i++) {String[] get = treeList.get(i);if (id.equals(get[0])) {if (!"1".equals(get[3])) {level++;searchLevel(get[3]);}break;}}
}
折叠/展开/搜索 所有节点
// 折叠所有节点    
public static void collapseAllNodes(javax.swing.JTree tree) {IconTreeNode root = (IconTreeNode) tree.getModel().getRoot();collapseAllNodes(tree, new TreePath(root));
}private static void collapseAllNodes(javax.swing.JTree tree, TreePath parentPath) {IconTreeNode node = (IconTreeNode) parentPath.getLastPathComponent();if (node.getChildCount() >= 0) {for (int i = 0; i < node.getChildCount(); i++) {IconTreeNode child = (IconTreeNode) node.getChildAt(i);TreePath path = parentPath.pathByAddingChild(child);collapseAllNodes(tree, path);}}tree.collapsePath(parentPath);
}// 展开所有节点
public static void expandAllNodes(javax.swing.JTree tree) {IconTreeNode root = (IconTreeNode) tree.getModel().getRoot();expandAllNodes(tree, new TreePath(root));
}private static void expandAllNodes(javax.swing.JTree tree, TreePath parentPath) {IconTreeNode node = (IconTreeNode) parentPath.getLastPathComponent();if (node.getChildCount() >= 0) {for (int i = 0; i < node.getChildCount(); i++) {IconTreeNode child = (IconTreeNode) node.getChildAt(i);TreePath path = parentPath.pathByAddingChild(child);expandAllNodes(tree, path);}}tree.expandPath(parentPath);
}// 搜索节点
public static void expandAndSelectNodes(javax.swing.JTree tree, String searchString) {IconTreeNode root = (IconTreeNode) tree.getModel().getRoot();expandAndSelectNodes(tree, new TreePath(root), searchString);
}private static boolean containsIgnoreCase(String text, String searchString) {return text.toLowerCase().contains(searchString.toLowerCase());
}private static void expandAndSelectNodes(javax.swing.JTree tree, TreePath parentPath, String searchString) {IconTreeNode node = (IconTreeNode) parentPath.getLastPathComponent();if (node.getChildCount() >= 0) {for (int i = 0; i < node.getChildCount(); i++) {IconTreeNode child = (IconTreeNode) node.getChildAt(i);TreePath path = parentPath.pathByAddingChild(child);// 判断节点名是否包含搜索字符串if (containsIgnoreCase(child.toString(), searchString)) {// 展开路径tree.expandPath(path);// 选择路径tree.setSelectionPath(path);}expandAndSelectNodes(tree, path, searchString);}}
}
切换按钮JToggleButton
        jToggleButton1.setText("全部(切换)");jToggleButton1.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {boolean selected = jToggleButton1.isSelected();DefaultTableModel model = (DefaultTableModel) jTable1.getModel();List<String[]> listTmp = new ArrayList<>();if (selected) {jToggleButton1.setText("差异(切换)");for (int i = 0; i < tableList.size(); i++) {String[] strs = tableList.get(i);if (!strs[1].equals(strs[4])) {listTmp.add(strs);}}} else {jToggleButton1.setText("全部(切换)");for (int i = 0; i < tableList.size(); i++) {String[] strs = tableList.get(i);listTmp.add(strs);}}TableOperate.setTModelData(model, listTmp);}});
时间选择JSpinner
// 定义
final javax.swing.JSpinner spinner = new javax.swing.JSpinner(model);
javax.swing.JSpinner.DateEditor editor = new javax.swing.JSpinner.DateEditor(spinner, "yyyy-MM-dd HH");
spinner.setEditor(editor);
spinner.setValue(new java.util.Date());
upJPanel.add(spinner);
// 使用
final java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH");
String sj = sdf.format(spinner.getValue());

swing项目经验笔记

弹出加载界面

功能点使用

        JFrame frame = (JFrame) tabPanel.getRootPane().getParent();Thread extractDataThread = new Thread(new extractDataThread());  //启动数据导入线程extractDataThread.start();WaitingDialogFactory.popUpWaitingDialog(frame, extractDataThread, "数据提取中...");frame.validate();if(flagq){Msg("联络线数据提取成功,请点击“保存”保存到数据库!");}

线程在类中定义

    class extractDataThread extends Thread {@Overridepublic void run() {try {lock.lock();extractData();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}}

注意线程同步加锁

    static ReentrantLock lock = new ReentrantLock();

标签页相关

标签页通过增加标签页的方式添加图例说明并重定向点击事件

        jTabbedPane1.addTab("", GetResources.getImageIcon(Constant.XianluImg), null);jTabbedPane1.addTab("", GetResources.getImageIcon(Constant.MuxianImg), null);jTabbedPane1.addTab("", GetResources.getImageIcon(Constant.ZhubianImg), null);jTabbedPane1.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {for (int i = 0; i < jTabbedPane1.getTabCount(); i++) {Rectangle rect = jTabbedPane1.getBoundsAt(i); //拿到标签的边界if (rect.contains(e.getX(), e.getY())) { //判断是否点在边界内if(i>=5){jTabbedPane1.setSelectedComponent(jPanel2);}}}}});

JPanel添加带标题的边框

        Font titleFont = new Font("Serif", Font.BOLD, 18);TitledBorder border = new TitledBorder(title); // title为String类型的标题border.setTitleFont(titleFont); // 字体border.setTitleColor(grayColor); // 字体颜色border.setTitleJustification(TitledBorder.LEFT); // 标题对齐方式border.setTitlePosition(TitledBorder.TOP); // 标题位置// 在面板上应用边框panel.setBorder(border);

JTabel设置表格渲染样式

        DefaultTableCellRenderer renderer = new DefaultTableCellRenderer() {@Overridepublic Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);// 设置内容居中setHorizontalAlignment(SwingConstants.CENTER);// 添加单元格提示框并设置内容setToolTipText((String) value);//设置偶数行底色if (row % 2 == 0) {setBackground(Constant.C_TABLE_OBG);setForeground(Constant.C_TABLE_OFG);} else if (row % 2 == 1) {setBackground(Constant.C_TABLE_J_BG);setForeground(Constant.C_TABLE_J_FG);}// 根据某列的内容设置字体颜色和背景色if (column == 1) {String aa = table.getValueAt(row, 1).toString();if (aa.equals("待完成")) {setForeground(Color.YELLOW);} else if (aa.equals("已完成")) {setForeground(Color.GREEN);} else if (aa.equals("未完成")) {setForeground(Color.RED);}}table.setFont(Constant.F_TABLE_TEXT);table.setGridColor(Constant.C_TABLE_BORDER);setBorder(new MatteBorder(0, 0, 1, 1, Constant.C_TABLE_BORDER));int columncou = table.getColumnCount();if (!table.getColumnSelectionAllowed()) {table.setColumnSelectionInterval(0, columncou - 1);}return component;}};// 将渲染方式应用到每一列for (int i = 0; i < table.getColumnCount(); i++) {table.getColumnModel().getColumn(i).setCellRenderer(renderer);}

关于JTabel

单元格渲染类

单元格渲染类:DefaultTableCellRenderer,这个类继承了JLabel,所以可以设置使用JLabel有的所有属性和方法

表格设置单元格tooltip和背景色等
        TableColumn col5 = fixTable.getColumnModel().getColumn(5);col5.setCellRenderer(new DefaultTableCellRenderer(){@Overridepublic Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {if (row % 2 == 0) {setBackground(new Color(231, 236, 252));setForeground(new Color(0, 0, 0));} else if (row % 2 == 1) {setBackground(new Color(178, 205, 255));setForeground(new Color(0, 0, 0));}setText((String) value);setToolTipText((String) value);return this;}});
设置表头行
		JTableHeader tableHeader = jTable1.getTableHeader();Font headerFont = new Font("宋体", Font.PLAIN, 10);tableHeader.setFont(headerFont);// 设置无边框header.setBorder(BorderFactory.createEmptyBorder());tableHeader.setDefaultRenderer(new DefaultTableCellRenderer() {@Overridepublic Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);// 设置无边框label.setBorder(BorderFactory.createEmptyBorder());// 居中label.setHorizontalAlignment(SwingConstants.CENTER);label.setForeground(new Color(148, 148, 148));return label;}});// 设置宽度为默认,高度为35tableHeader.setPreferredSize(new Dimension(jTable1.getPreferredSize().width, 35));jTable1.setTableHeader(tableHeader);
单独设置表头居中
// 设置表头文本居中
DefaultTableCellRenderer headerRenderer = (DefaultTableCellRenderer) table.getTableHeader().getDefaultRenderer();
headerRenderer.setHorizontalAlignment(JLabel.CENTER);
设置表格表头居中换行

使用html格式

        qTable1.setModel(new javax.swing.table.DefaultTableModel(new Object[][]{},new String[]{"时间:", "日前", "日内", "实际", "<html><center>偏差<br/>(日内-实际)</center></html>", "时间:", "日前", "日内"}) {Class[] types = new Class[]{java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class,java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class};boolean[] canEdit = new boolean[]{false, false, false, false, false, false, true, false};public Class getColumnClass(int columnIndex) {return types[columnIndex];}public boolean isCellEditable(int rowIndex, int columnIndex) {return canEdit[columnIndex];}});
设置网格线不显示
// 设置表格线为不显示
table.setShowGrid(false);
设置行高
table.setRowHeight(30); // 设置行高为 30 像素
设置数据
        DefaultTableModel model = (DefaultTableModel) jTable1.getModel();model.addRow(new String[]{"1", "机组名称11", "燃气机组", "2024-04-10", "2024-05-12"});model.addRow(new String[]{"2", "机组名称22", "燃气机组", "2024-04-12", "2024-05-19"});model.addRow(new String[]{"3", "机组名称33", "燃气机组", "2024-04-13", "2024-05-16"});model.addRow(new String[]{"4", "机组名称44", "燃气机组", "2024-04-15", "2024-05-12"});model.addRow(new String[]{"5", "机组名称55", "燃气机组", "2024-04-17", "2024-05-02"});

或者

// 有TableOperate公共类的情况下,陕西现货子系统、北京校核系统
TableOperate.setTModelData(tmp8, list8);
清除数据
qTable1.getTmodel().setRowCount(0);

或者

jTable.setModel(new DefaultTableModel()); // 使用一个新的空表格模型

或者

DefaultTableModel model = (DefaultTableModel) jTable.getModel();
while (model.getRowCount() > 0) {model.removeRow(0); // 删除第一行数据
}
不允许列排序
DefaultTableModel model = (DefaultTableModel) qTable10.getModel();
TableRowSorter<DefaultTableModel> sorter = new TableRowSorter<>(model);
qTable10.setRowSorter(sorter);
sorter.setSortable(0, false);

或者

qTable1.setRowSorter(null);
表头不可拖拽移动位置
qTable2.getTableHeader().setReorderingAllowed(false);
设置右键菜单
    private void qTable1MousePressed(java.awt.event.MouseEvent evt) {                                     // TODO add your handling code here:int selcolumn = qTable1.getSelectedColumn();if (selcolumn == 3) {//鼠标右键事件,批量设置为是或者否if (evt.getButton() == 3) {rows = qTable1.getSelectedRows();if (rows.length <= 0) {return;}String pdate = jDatePicker1.getSelectedItem().toString();
//                System.out.println("pdate  " + pdate + "    nowdate  " + nowdate + "    startIndex  " + startIndex);if (nowdate > Integer.parseInt(pdate.replace("-", ""))) {Msg("包含历史时刻,不可选择修改");qTable1.clearSelection();//清除行选中状态return;} else {
//                    startIndex = rows[0];int h = Integer.parseInt(dtfH.format(LocalDateTime.now()));int m = Integer.parseInt(dtfM.format(LocalDateTime.now()));startIndex = (h * 12) + (m / 5 + 1);ActionListener popupmenuClicked = new java.awt.event.ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {Object MenuObject = e.getSource();String MenuName = e.getActionCommand();if (MenuObject instanceof QMenuItem) {if (MenuName.equals("批量设置数值")) {String setpower = JOptionPane.showInputDialog("设置数值:");if (setpower == null || "".equals(setpower)) {Msg("值为空,请重新设置");return;}if (check.checkData("出力值", setpower, 10, 2, true, true)) {for (int i = rows.length - 1; i >= 0; i--) {
//                                            System.out.println(i + "  rows[i]  " + rows[i] + "    startIndex  " + startIndex);if (rows[i] >= startIndex) {//只写可编辑时刻点之后数据setpower = setpower == null || "".equals(setpower) ? qTable2.getValueAt(rows[i], 4).toString() : setpower;qTable1.setValueAt(setpower, rows[i], 3);} else {Msg("包含历史时刻,该部分未作修改");return;}}}}}}};popupmenu.removeAll();QMenuItem ls_menuitem = new QMenuItem();ls_menuitem.setText("批量设置数值");ls_menuitem.setFont(TopicStyle.F_JBUTTON_TEXT);ls_menuitem.setForeground(TopicStyle.C_JLABEL_BG);ls_menuitem.addActionListener(popupmenuClicked);popupmenu.add(ls_menuitem);this.add(popupmenu);popupmenu.show(qTable1, evt.getX(), evt.getY());}}}}        
选择单元格
// 设置表格单选行        
qTable1.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// 设置表格多选单元格
qTable2.setColumnSelectionAllowed(true);  // 允许列选择
选择单元格监听事件
        table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {@Overridepublic void valueChanged(ListSelectionEvent e) {int row = table.getSelectedRow();int col = table.getSelectedColumn();if (row >= 0 && col >= 0) {Object selectedValue = table.getValueAt(row, col);System.out.println("选择了  "+row+" "+col);loadPlantChart(table);}}});
删除列并刷新表格
table.getColumnModel().removeColumn(table.getColumnModel().getColumn(columnIndex)); // 删除列((DefaultTableModel) 
设置单元格不可编辑
        table.setModel(new DefaultTableModel(){@Overridepublic boolean isCellEditable(int row, int col) {return false;}});

关于JLabel

文本居中

setHorizontalAlignment和setHorizontalTextPosition有什么区别?

  1. setHorizontalAlignment(int alignment) 方法用于设置标签中文本的水平对齐方式,可以控制文本在标签中水平方向上的对齐方式。参数 alignment 可以接受以下常量值之一:

    • SwingConstants.LEFT:文本左对齐。
    • SwingConstants.CENTER:文本居中对齐。
    • SwingConstants.RIGHT:文本右对齐。

    这个方法影响的是文本在标签组件内的水平位置。

  2. setHorizontalTextPosition(int textPosition) 方法用于设置标签中文本相对于图标的水平位置。参数 textPosition 可以接受以下常量值之一:

    • SwingConstants.LEFT:文本在图标的左侧。
    • SwingConstants.CENTER:文本与图标水平居中对齐。
    • SwingConstants.RIGHT:文本在图标的右侧。
    • SwingConstants.LEADING:文本在图标之前,通常表示从左到右的语言文本在左侧,从右到左的语言文本在右侧。
    • SwingConstants.TRAILING:文本在图标之后,通常表示从左到右的语言文本在右侧,从右到左的语言文本在左侧。

    这个方法影响的是文本与图标之间的相对位置。

鼠标悬浮提示
		// 设置鼠标悬停提示label.setToolTipText("This is a tooltip");
粗斜体
		// 创建粗斜体字体Font font = new Font("Serif", Font.BOLD + Font.ITALIC, 16);label.setFont(font);

鼠标悬浮显示菜单

		// 创建一个弹出菜单JPopupMenu popupMenu = new JPopupMenu();popupMenu.setLayout(new GridLayout(3, 1)); // 设置弹出菜单为网格布局// 向弹出菜单中添加多个 JLabelJLabel item1 = new JLabel("Item 1");JLabel item2 = new JLabel("Item 2");JLabel item3 = new JLabel("Item 3");popupMenu.add(item1);popupMenu.add(item2);popupMenu.add(item3);// 添加鼠标监听器,显示/隐藏弹出菜单label.addMouseListener(new MouseAdapter() {@Overridepublic void mouseEntered(MouseEvent e) {// 计算弹出菜单的位置int x = label.getLocationOnScreen().x;int y = label.getLocationOnScreen().y + label.getHeight();// 显示弹出菜单popupMenu.show(label, x, y);}@Overridepublic void mouseExited(MouseEvent e) {// 隐藏弹出菜单popupMenu.setVisible(false);}});

布局相关

FlowLayout上下居中

添加空的JLabel占位

或者

// 创建包含组件的 JPanel
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0)); // 居中对齐,水平间距为 0,垂直间距为 0

边框Border相关

swing中的几种Border有什么区别和特点?

在Java Swing中,Border是用于为组件添加边框装饰的对象。Swing提供了几种不同类型的Border,每种类型都具有不同的外观和特点。以下是几种常见的Border类型及其区别和特点:

  1. EmptyBorder:

    • EmptyBorder是一种简单的边框,不显示任何装饰或边框。
    • 它可以用来创建组件之间的空白间距。
  2. LineBorder:

    • LineBorder显示一个简单的边框,可以设置边框的颜色和粗细。
    • 可以用于突出显示组件的边缘。
  3. BevelBorder:

    • BevelBorder创建一个斜面或斜角边框,可以凸出或凹入组件。
    • 可以通过设置类型(凸出或凹入)、高亮色和阴影色来定制边框外观。
  4. EtchedBorder:

    • EtchedBorder显示一个凹槽或凹槽边框,类似于BevelBorder,但没有斜角。
    • 可以通过设置类型(凹槽或凹槽)、高亮色和阴影色来定制边框外观。
  5. TitledBorder:

    • TitledBorder在组件周围绘制一个标题和边框。
    • 可以用于为组件提供标题,并根据需要定制边框的外观。

这些边框类型可以单独使用,也可以组合使用,以创建复杂的边框效果。通过选择适当的Border类型,并根据需要进行自定义,可以为Swing界面增添丰富的外观和样式。

杂项组件

分割线JSeparator
		JSeparator separator = new JSeparator(SwingConstants.VERTICAL); // 创建垂直分隔符JSeparator separator = new JSeparator(SwingConstants.HORIZONTAL); // 水平separator.setPreferredSize(new Dimension(10, 50)); // 设置分隔符的尺寸panel.add(separator);
下拉列表JComboBox
添加属性监听
		comboBox.addItemListener(new ItemListener() {@Overridepublic void itemStateChanged(ItemEvent e) {// 如果是选择项发生改变if (e.getStateChange() == ItemEvent.SELECTED) {// 获取新的选项值String selectedOption = (String) comboBox.getSelectedItem();// 输出新的选项值System.out.println("Selected option: " + selectedOption);}}});

判断退出页面

判断是否还在显示,可用于切换功能页的判断

this.isDisplayable();

使用线程池自动刷新

private final ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1);scheduledThreadPoolExecutor.scheduleWithFixedDelay(this::scheduleGetData,60,1, TimeUnit.SECONDS);public void scheduleGetData(){if (!this.isDisplayable()) {log.info("view is removed cancel scheduledThreadPoolExecutor");log.info("页面关闭,关闭线程池");scheduledThreadPoolExecutor.shutdownNow();return;}//log.info("定时一分钟执行一次");String dateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));String seconds = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")).substring("yyyy-MM-dd HH:mm:".length(), "yyyy-MM-dd HH:mm:ss".length());if (!StrUtil.equals("00",seconds)) {//log.info("非整点,只在整点刷新!!!");return;}log.info("{}整点刷新中!!!",dateTime);getData();}

设置样式不生效(异步)

尝试在EDT(事件分发线程)中更新

        SwingUtilities.invokeLater(new Runnable() {@Overridepublic void run() {jLabel4.setFont(new java.awt.Font("宋体", 1, 22));jLabel14.setFont(new java.awt.Font("宋体", 1, 22));}});

使用SwingWorker

基本使用
    private void startBackgroundTask() {// 创建 SwingWorker 实例SwingWorker<Void, String> worker = new SwingWorker<Void, String>() {@Overrideprotected Void doInBackground() throws Exception {for (int i = 0; i <= 100; i += 10) {Thread.sleep(500); // 模拟耗时操作publish("Progress: " + i + "%");}publish("Task completed!");return null;}@Overrideprotected void process(List<String> chunks) {// 更新界面for (String message : chunks) {textArea.append(message + "\n");}}@Overrideprotected void done() {// 可选:任务完成后的操作// 如更新界面状态、显示提示信息等}};// 启动 SwingWorkerworker.execute();}
两个泛型参数

SwingWorker 类有两个泛型参数类型:

  1. T:表示后台任务的执行结果类型。
  2. V:表示中间结果(进度更新或部分结果)的类型。

通常情况下,如果后台任务只需要返回一个结果而不需要中间过程的更新,可以将 V 设置为 Void,即不传递中间结果。这时,SwingWorker 的泛型类型就变成了 SwingWorker<T, Void>

如果后台任务需要在执行过程中更新界面或者传递部分结果,就可以使用第二个参数 V。在这种情况下,SwingWorker 的泛型类型就是 SwingWorker<T, V>

下面是使用 SwingWorker 时如何理解和使用这两个参数类型:

  • T:指定 doInBackground() 方法的返回值类型,也就是后台任务执行完毕后的结果类型。可以是任何 Java 类型,例如 IntegerString、自定义类等。注意Void是Void不是void
  • V:指定 publish() 方法和 process() 方法的参数类型,用于在后台任务执行过程中发布中间结果或进度更新,并在 EDT 中接收并处理这些中间结果。

SwingWorker 的子类中,通常需要重写以下方法:

  1. doInBackground():执行后台任务的方法,在这个方法中编写耗时操作。方法的返回值类型应该和 T 类型一致。
  2. process():处理中间结果的方法,在这个方法中更新界面或处理进度信息。方法的参数类型应该和 V 类型一致。
  3. done()(可选):后台任务执行完成后的回调方法,在这个方法中进行一些清理工作或者显示最终结果。
publish()方法和process()方法

SwingWorker 类的 publish() 方法和 process() 方法是用于在后台任务中与主线程(EDT)进行交互的两个重要方法。它们允许在后台任务执行期间更新 Swing 组件的内容,而不会阻塞用户界面。

publish() 方法

publish() 方法用于从后台任务中发送数据到主线程(EDT)。它可以在 doInBackground() 方法中调用,用来将中间结果传递给 process() 方法。

  • 方法签名protected final void publish(V... chunks)
  • 参数:可变参数 chunks 表示要传递到 process() 方法的数据片段。

process() 方法

process() 方法在 EDT 线程中执行,用于处理从 publish() 方法传递过来的数据。它通常用于更新 Swing 组件的状态或界面。

  • 方法签名protected void process(List<V> chunks)
  • 参数chunks 是一个列表,包含从 publish() 方法传递过来的数据片段。

工作流程

  1. 后台任务中的 publish() 方法
    • doInBackground() 方法中,当需要将数据传递给 EDT 时,调用 publish() 方法并传递数据片段。
    • 例如:publish(progressString);
  2. 主线程(EDT)中的 process() 方法
    • SwingWorker 会自动将通过 publish() 发布的数据传递给 process() 方法。
    • process() 方法中,你可以处理这些数据并更新 Swing 组件。
    • 例如:更新进度条或文本区域的内容。

北京项目通用

使用统一的主题
        com.qctc.view.common.theme.MyInterpro.MyInterpro(this.getComponents());

导出下载Excel

        JFileChooser fileChooser = new JFileChooser();int result = fileChooser.showSaveDialog(this);if (result == JFileChooser.APPROVE_OPTION) {File file = fileChooser.getSelectedFile();try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {writer.write(textArea.getText());JOptionPane.showMessageDialog(this, "File saved successfully.");} catch (IOException e) {JOptionPane.showMessageDialog(this, "Error saving file: " + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);}}

导出某个JTable的内容为excel

XSSFCellStyle styleData = wb.createCellStyle();
styleData.setBorderTop((short) 1);
styleData.setBorderBottom((short) 1);
styleData.setBorderLeft((short) 1);
styleData.setBorderRight((short) 1);
styleData.setFont(fontData);
styleData.setAlignment(HorizontalAlignment.CENTER);
styleData.setVerticalAlignment(VerticalAlignment.CENTER);

文章转载自:

http://rukjThtd.Ltpzr.cn
http://gULGTEnF.Ltpzr.cn
http://d6r4jeVP.Ltpzr.cn
http://0igiLJ3n.Ltpzr.cn
http://HYF0ECLB.Ltpzr.cn
http://Ltk1gXTU.Ltpzr.cn
http://1IMrvnyy.Ltpzr.cn
http://gNcMqL6u.Ltpzr.cn
http://lCiTHR8h.Ltpzr.cn
http://38hTOHMp.Ltpzr.cn
http://9QoL51qO.Ltpzr.cn
http://oPHRjMDe.Ltpzr.cn
http://OOChY5mB.Ltpzr.cn
http://fkWkrRpx.Ltpzr.cn
http://MLpb2Yns.Ltpzr.cn
http://3zJEkHZ7.Ltpzr.cn
http://swHnmhZG.Ltpzr.cn
http://ewI61gqE.Ltpzr.cn
http://0siVlB5W.Ltpzr.cn
http://j1uxbTZM.Ltpzr.cn
http://f6vj0U1c.Ltpzr.cn
http://CsELoUkg.Ltpzr.cn
http://9hcMCFUP.Ltpzr.cn
http://G225r15K.Ltpzr.cn
http://D2y2Rt56.Ltpzr.cn
http://i2cRIw7H.Ltpzr.cn
http://9Gl4w4FX.Ltpzr.cn
http://fj5L09rR.Ltpzr.cn
http://ocXQUy4n.Ltpzr.cn
http://dbTO3829.Ltpzr.cn
http://www.dtcms.com/a/369714.html

相关文章:

  • IPD模式下跨部门团队管理
  • Transformer核心—自注意力机制
  • 可搜索且多选的下拉式列表
  • 《C++ printf()函数的深度解析》
  • HTML基础(决定页面结构)
  • Modbus RTU 协议介绍
  • 掌握RabbitMQ核心战法:从消息确认到高可用集群
  • C++数据结构命名:从规范到艺术的深度解析
  • 前后端国密加密传输用户密码流程
  • [2025.9.5]Win11.26H2.27934.1 IoT 金丝雀轻度精简优化版 PIIS出品
  • 无名信号量
  • IPD变革,是中国企业实现产品与技术领先之路
  • 在Windows中已经启动的容器(比如xinference),如何设置让其在每次Docker启动时能自动启动
  • 支付DDD建模
  • Nginx 配置详解与虚拟主机实战指南
  • 驱动员工的核心:少谈“大道理”,多解“人心”
  • 【LLM】使用 Transformer 强化学习的 GRPO
  • 【代码随想录算法训练营——Day3】链表——203.移除链表元素、707.设计链表、206.反转链表
  • 目标检测双雄:一阶段与二阶段检测器全解析
  • 2025高教社数学建模国赛C题 - NIPT的时点选择与胎儿的异常判定(完整参考论文)
  • keil 5 STM32工程介绍
  • C/C++包管理工具:Conan
  • 标注格式转换csv转xml
  • 错误是ModuleNotFoundError: No module named ‘pip‘解决“找不到 pip”
  • 文章采集发布帝国ECMS网站技巧
  • 创新、绿色、共赢:芬兰企业在华发展战略与案例解析(2025中芬建交75周年)
  • PAIN | 痛在你身,激活在我脑:原来后侧默认模式网络是‘感同身受’的神经开关
  • 【C++】Vector完全指南:动态数组高效使用
  • 状压 dp --- TSP 问题
  • 【数字孪生核心技术】什么是倾斜摄影?