swing
JFrame
jframe是一个顶层容器
创建jframe并设置标题为Swing
java
JFrame frame = new JFrame("Swing");
显示JFrame
java
frame.setVisible(true);
退出swing应用
java
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的大小设置
java
frame.setSize(int width,int height);
JFrame的位置设置
java
frame.setLocation(int x,int y);
同时设置位置和大小
java
frame.setBounds(int x,int y,int widht,int height);
添加组件
要将JFrame放在屏幕中央,使用null参数调用其setLocationRelativeTo()方法
当向JFrame添加UI控件时,需要将其添加到JFrame的内容窗格
获取内容窗格的引用及添加
java
Container contentPane = frame.getContentPane();
contentPane.add(aComponent); //aComponent为UI组件
添加一个按钮Close
java
frame.getContentPane().add(new JButton("Close"));
包JFrame
JFrame的pack()方法检查JFrame上的所有组件,并决定它们的首选大小,并设置JFrame的大小刚好足以显示所有组件
当我们调用pack()方法时,我们不需要设置JFrame的大小,pack()方法将计算JFrame的大小并设置它
当使用pack()方法时,我们不需要调用setBounds()方法,要在pack()方法后定位JFrame,请使用setLocation(x,y)方法
JFrame状态
设置JFrame的状态
java
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
状态常量
JFrame状态常量 | 描述 |
---|---|
NORMAL | JFrame以正常大小显示。 |
ICONIFIED | JFrame显示为最小化状态。 |
MAXIMIZED_HORIZ | JFrame显示为水平最大化,但垂直尺寸正常。 |
MAXIMIZED_VERT | JFrame显示为水平最大化,但垂直尺寸正常。... |
MAXIMIZED_BOTH | JFrame显示为水平和垂直最大化。 |
默认按钮
将自定义的按钮设置为默认按钮
java
// Create a JButton
JButton okButton = new JButton("OK");
// Set okButton as the default button
frame.getRootPane().setDefaultButton(okButton);
窗口事件
可以使用WindowListener接口和WindowAdapter类
java
JFrame frame = new JFrame();
frame.addWindowListener(new WindowListener() {
@Override
public void windowOpened(WindowEvent e) {
System.out.println("JFrame has been made visible first time");
}
@Override
public void windowClosing(WindowEvent e) {
System.out.println("JFrame is closing.");
}
@Override
public void windowClosed(WindowEvent e) {
System.out.println("JFrame is closed.");
}
@Override
public void windowIconified(WindowEvent e) {
System.out.println("JFrame is minimized.");
}
@Override
public void windowDeiconified(WindowEvent e) {
System.out.println("JFrame is restored.");
}
@Override
public void windowActivated(WindowEvent e) {
System.out.println("JFrame is activated.");
}
@Override
public void windowDeactivated(WindowEvent e) {
System.out.println("JFrame is deactivated.");
}
});
// Use the WindowAdapter class to intercept only the window closing event
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.out.println("JFrame is closing.");
}
});
dispose()方法使窗口不可见,并将资源释放到操作系统。
Swing布局管理器
容器使用布局管理器来定位其所有组件
JFrame的内容窗格的默认布局管理器时BorderLayout
JPanel的默认布局管理器是FlowLayout
可以使用setLayout()方法更改,传入null则为删除布局管理器
容器的getLayout()方法返回容器当前正在使用的布局管理器的引用
java
JFrame frame = new JFrame("Frame");
Container contentPane = frame.getContentPane();
contentPane.setLayout(new FlowLayout());
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
空布局管理器
也称为绝对定位,使用setBounds()方法设置组件的位置
java
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()方法
java
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);
流式布局尝试将所有组件放入一行,给他们的首选大小
如果所有组件不适合一行,则会启动另一行
流式布局可以为宽度和高度添加额外的空间
设置对齐
java
FlowLayout flowLayout = new FlowLayout(FlowLayout.RIGHT);
FlowLayout flowLayout = new FlowLayout(FlowLayout.LEFT);
flowLayout.setAlignment(FlowLayout.RIGHT);
5种对齐方式
- LEFT
- RIGHT
- CENTER
- LEADING
- TRAILING
BorderLayout边框布局
容器上的组件按照上北下南左西右东的顺序摆放
java
// 设置布局器为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网格布局
java
// 设置布局器为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建议大小,只对部分布局有效
java
b3.setPreferredSize(new Dimension(180,40));
CardLayout卡片布局
卡片布局将容器分成许多层,每层的显示空间占据整个容器的大小,但是每层只允许放置一个组件
GridBagLayout网格包布局'
网格包布局不需要组件的尺寸一致,允许组件扩展到多行多列
BoxLayout盒布局
盒布局通常和Box容器联合使用
组件
标签JLable
标签是可以包含文本和图像的非交互组件
按钮JButton
点击按钮弹出新窗口查看日志
java
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
};
@Override
public 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
添加选择项监听事件
java
qCombox1.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
String selectedOption = (String) qCombox1.getSelectedItem();
qLabel6.setText(idMap.getOrDefault(selectedOption, ""));
}
}
});
模拟用户点击
java
jRadioButton2.doClick()
列表框JList
树JTree
设置字体颜色
java
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);
设置单选
java
jTree1.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
选择事件
java
jTree1.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
@Override
public 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]); // ID
List<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;
}
}
}
}
});
递归加载树的数据
java
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);
}
}
}
搜索树的层级
java
// 定义变量
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;
}
}
}
折叠/展开/搜索 所有节点
java
// 折叠所有节点
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
java
jToggleButton1.setText("全部(切换)");
jToggleButton1.addActionListener(new ActionListener() {
@Override
public 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
java
// 定义
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项目经验笔记
弹出加载界面
功能点使用
java
JFrame frame = (JFrame) tabPanel.getRootPane().getParent();
Thread extractDataThread = new Thread(new extractDataThread()); //启动数据导入线程
extractDataThread.start();
WaitingDialogFactory.popUpWaitingDialog(frame, extractDataThread, "数据提取中...");
frame.validate();
if(flagq){
Msg("联络线数据提取成功,请点击"保存"保存到数据库!");
}
线程在类中定义
java
class extractDataThread extends Thread {
@Override
public void run() {
try {
lock.lock();
extractData();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
注意线程同步加锁
java
static ReentrantLock lock = new ReentrantLock();
标签页相关
标签页通过增加标签页的方式添加图例说明并重定向点击事件
java
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() {
@Override
public 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添加带标题的边框
java
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设置表格渲染样式
java
DefaultTableCellRenderer renderer = new DefaultTableCellRenderer() {
@Override
public 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和背景色等
java
TableColumn col5 = fixTable.getColumnModel().getColumn(5);
col5.setCellRenderer(new DefaultTableCellRenderer(){
@Override
public 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;
}
});
设置表头行
java
JTableHeader tableHeader = jTable1.getTableHeader();
Font headerFont = new Font("宋体", Font.PLAIN, 10);
tableHeader.setFont(headerFont);
// 设置无边框
header.setBorder(BorderFactory.createEmptyBorder());
tableHeader.setDefaultRenderer(new DefaultTableCellRenderer() {
@Override
public 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;
}
});
// 设置宽度为默认,高度为35
tableHeader.setPreferredSize(new Dimension(jTable1.getPreferredSize().width, 35));
jTable1.setTableHeader(tableHeader);
单独设置表头居中
java
// 设置表头文本居中
DefaultTableCellRenderer headerRenderer = (DefaultTableCellRenderer) table.getTableHeader().getDefaultRenderer();
headerRenderer.setHorizontalAlignment(JLabel.CENTER);
设置表格表头居中换行
使用html格式
java
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];
}
});
设置网格线不显示
java
// 设置表格线为不显示
table.setShowGrid(false);
设置行高
java
table.setRowHeight(30); // 设置行高为 30 像素
设置数据
java
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"});
或者
java
// 有TableOperate公共类的情况下,陕西现货子系统、北京校核系统
TableOperate.setTModelData(tmp8, list8);
清除数据
java
qTable1.getTmodel().setRowCount(0);
或者
java
jTable.setModel(new DefaultTableModel()); // 使用一个新的空表格模型
或者
java
DefaultTableModel model = (DefaultTableModel) jTable.getModel();
while (model.getRowCount() > 0) {
model.removeRow(0); // 删除第一行数据
}
不允许列排序
java
DefaultTableModel model = (DefaultTableModel) qTable10.getModel();
TableRowSorter<DefaultTableModel> sorter = new TableRowSorter<>(model);
qTable10.setRowSorter(sorter);
sorter.setSortable(0, false);
或者
java
qTable1.setRowSorter(null);
表头不可拖拽移动位置
java
qTable2.getTableHeader().setReorderingAllowed(false);
设置右键菜单
java
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() {
@Override
public 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());
}
}
}
}
选择单元格
java
// 设置表格单选行
qTable1.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// 设置表格多选单元格
qTable2.setColumnSelectionAllowed(true); // 允许列选择
选择单元格监听事件
java
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public 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);
}
}
});
删除列并刷新表格
java
table.getColumnModel().removeColumn(table.getColumnModel().getColumn(columnIndex)); // 删除列
((DefaultTableModel)
设置单元格不可编辑
java
table.setModel(new DefaultTableModel(){
@Override
public boolean isCellEditable(int row, int col) {
return false;
}
});
关于JLabel
文本居中
setHorizontalAlignment和setHorizontalTextPosition有什么区别?
-
setHorizontalAlignment(int alignment)
方法用于设置标签中文本的水平对齐方式,可以控制文本在标签中水平方向上的对齐方式。参数 alignment 可以接受以下常量值之一:SwingConstants.LEFT
:文本左对齐。SwingConstants.CENTER
:文本居中对齐。SwingConstants.RIGHT
:文本右对齐。
这个方法影响的是文本在标签组件内的水平位置。
-
setHorizontalTextPosition(int textPosition)
方法用于设置标签中文本相对于图标的水平位置。参数 textPosition 可以接受以下常量值之一:SwingConstants.LEFT
:文本在图标的左侧。SwingConstants.CENTER
:文本与图标水平居中对齐。SwingConstants.RIGHT
:文本在图标的右侧。SwingConstants.LEADING
:文本在图标之前,通常表示从左到右的语言文本在左侧,从右到左的语言文本在右侧。SwingConstants.TRAILING
:文本在图标之后,通常表示从左到右的语言文本在右侧,从右到左的语言文本在左侧。
这个方法影响的是文本与图标之间的相对位置。
鼠标悬浮提示
java
// 设置鼠标悬停提示
label.setToolTipText("This is a tooltip");
粗斜体
java
// 创建粗斜体字体
Font font = new Font("Serif", Font.BOLD + Font.ITALIC, 16);
label.setFont(font);
鼠标悬浮显示菜单
java
// 创建一个弹出菜单
JPopupMenu popupMenu = new JPopupMenu();
popupMenu.setLayout(new GridLayout(3, 1)); // 设置弹出菜单为网格布局
// 向弹出菜单中添加多个 JLabel
JLabel 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() {
@Override
public void mouseEntered(MouseEvent e) {
// 计算弹出菜单的位置
int x = label.getLocationOnScreen().x;
int y = label.getLocationOnScreen().y + label.getHeight();
// 显示弹出菜单
popupMenu.show(label, x, y);
}
@Override
public void mouseExited(MouseEvent e) {
// 隐藏弹出菜单
popupMenu.setVisible(false);
}
});
布局相关
FlowLayout上下居中
添加空的JLabel占位
或者
java
// 创建包含组件的 JPanel
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0)); // 居中对齐,水平间距为 0,垂直间距为 0
边框Border相关
swing中的几种Border有什么区别和特点?
在Java Swing中,Border是用于为组件添加边框装饰的对象。Swing提供了几种不同类型的Border,每种类型都具有不同的外观和特点。以下是几种常见的Border类型及其区别和特点:
-
EmptyBorder:
- EmptyBorder是一种简单的边框,不显示任何装饰或边框。
- 它可以用来创建组件之间的空白间距。
-
LineBorder:
- LineBorder显示一个简单的边框,可以设置边框的颜色和粗细。
- 可以用于突出显示组件的边缘。
-
BevelBorder:
- BevelBorder创建一个斜面或斜角边框,可以凸出或凹入组件。
- 可以通过设置类型(凸出或凹入)、高亮色和阴影色来定制边框外观。
-
EtchedBorder:
- EtchedBorder显示一个凹槽或凹槽边框,类似于BevelBorder,但没有斜角。
- 可以通过设置类型(凹槽或凹槽)、高亮色和阴影色来定制边框外观。
-
TitledBorder:
- TitledBorder在组件周围绘制一个标题和边框。
- 可以用于为组件提供标题,并根据需要定制边框的外观。
这些边框类型可以单独使用,也可以组合使用,以创建复杂的边框效果。通过选择适当的Border类型,并根据需要进行自定义,可以为Swing界面增添丰富的外观和样式。
杂项组件
分割线JSeparator
java
JSeparator separator = new JSeparator(SwingConstants.VERTICAL); // 创建垂直分隔符
JSeparator separator = new JSeparator(SwingConstants.HORIZONTAL); // 水平
separator.setPreferredSize(new Dimension(10, 50)); // 设置分隔符的尺寸
panel.add(separator);
下拉列表JComboBox
添加属性监听
java
comboBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
// 如果是选择项发生改变
if (e.getStateChange() == ItemEvent.SELECTED) {
// 获取新的选项值
String selectedOption = (String) comboBox.getSelectedItem();
// 输出新的选项值
System.out.println("Selected option: " + selectedOption);
}
}
});
判断退出页面
判断是否还在显示,可用于切换功能页的判断
java
this.isDisplayable();
使用线程池自动刷新
java
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(事件分发线程)中更新
java
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
jLabel4.setFont(new java.awt.Font("宋体", 1, 22));
jLabel14.setFont(new java.awt.Font("宋体", 1, 22));
}
});
使用SwingWorker
基本使用
java
private void startBackgroundTask() {
// 创建 SwingWorker 实例
SwingWorker<Void, String> worker = new SwingWorker<Void, String>() {
@Override
protected Void doInBackground() throws Exception {
for (int i = 0; i <= 100; i += 10) {
Thread.sleep(500); // 模拟耗时操作
publish("Progress: " + i + "%");
}
publish("Task completed!");
return null;
}
@Override
protected void process(List<String> chunks) {
// 更新界面
for (String message : chunks) {
textArea.append(message + "\n");
}
}
@Override
protected void done() {
// 可选:任务完成后的操作
// 如更新界面状态、显示提示信息等
}
};
// 启动 SwingWorker
worker.execute();
}
两个泛型参数
SwingWorker
类有两个泛型参数类型:
- T:表示后台任务的执行结果类型。
- V:表示中间结果(进度更新或部分结果)的类型。
通常情况下,如果后台任务只需要返回一个结果而不需要中间过程的更新,可以将 V 设置为 Void
,即不传递中间结果。这时,SwingWorker
的泛型类型就变成了 SwingWorker<T, Void>
。
如果后台任务需要在执行过程中更新界面或者传递部分结果,就可以使用第二个参数 V 。在这种情况下,SwingWorker
的泛型类型就是 SwingWorker<T, V>
。
下面是使用 SwingWorker
时如何理解和使用这两个参数类型:
- T :指定
doInBackground()
方法的返回值类型,也就是后台任务执行完毕后的结果类型。可以是任何 Java 类型,例如Integer
、String
、自定义类等。注意Void是Void不是void - V :指定
publish()
方法和process()
方法的参数类型,用于在后台任务执行过程中发布中间结果或进度更新,并在 EDT 中接收并处理这些中间结果。
在 SwingWorker
的子类中,通常需要重写以下方法:
- doInBackground() :执行后台任务的方法,在这个方法中编写耗时操作。方法的返回值类型应该和 T 类型一致。
- process() :处理中间结果的方法,在这个方法中更新界面或处理进度信息。方法的参数类型应该和 V 类型一致。
- 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()
方法传递过来的数据片段。
工作流程
- 后台任务中的
publish()
方法 :- 在
doInBackground()
方法中,当需要将数据传递给 EDT 时,调用publish()
方法并传递数据片段。 - 例如:
publish(progressString);
- 在
- 主线程(EDT)中的
process()
方法 :SwingWorker
会自动将通过publish()
发布的数据传递给process()
方法。- 在
process()
方法中,你可以处理这些数据并更新 Swing 组件。 - 例如:更新进度条或文本区域的内容。
北京项目通用
使用统一的主题
java
com.qctc.view.common.theme.MyInterpro.MyInterpro(this.getComponents());
导出下载Excel
java
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
java
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);