package demo1;
import com.fazecast.jSerialComm.SerialPort;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.HashMap;
import java.util.Map;
public class TemperatureMonitorGUI extends JFrame {
private JLabel temperatureLabel;
private JLabel statusLabel;
private JButton connectButton;
private JButton readButton;
private JButton startControlButton;
private JButton refreshPortButton;
private JComboBox<String> portComboBox;
private JComboBox<String> baudRateComboBox;
private JComboBox<String> dateBiteComboBox;
private JComboBox<String> stopBitsComboBox;
private JComboBox<String> parityComboBox;
private JComboBox<String> modeComboBox;
private TemperatureController controller;
// 输入组件
private JTextField targetTempField;
private JTextField transitionTimeField;
private Map<String, Component> modeComponents = new HashMap<>();
// 曲线模式字段
private JTextField[] curveTempFields = new JTextField[3];
private JTextField[] curveDurationFields = new JTextField[3];
private JTextField[] curveHoldFields = new JTextField[3];
private JTextField finalTempField;
private JTextField finalTransitionField;
public TemperatureMonitorGUI() {
setTitle("MODBUS RTU 温控系统");
setSize(1100, 700); // 增加整体尺寸
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setBackground(new Color(240, 245, 250)); // 设置背景色
// 使用主面板管理布局
JPanel mainPanel = new JPanel(new BorderLayout(15, 15));
mainPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
add(mainPanel);
// 顶部温度显示面板 - 更醒目的设计
JPanel topPanel = createTopPanel();
mainPanel.add(topPanel, BorderLayout.NORTH);
// 中央区域使用网格袋布局
JPanel centerPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(8, 8, 8, 8); // 组件间距
gbc.fill = GridBagConstraints.BOTH;
// 左侧输入配置面板 - 宽度调整
JPanel inputPanel = createInputPanel();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 0.3; // 比例调整
gbc.weighty = 1.0;
centerPanel.add(inputPanel, gbc);
// 中间按钮面板 - 更紧凑
JPanel buttonPanel = createButtonPanel();
gbc.gridx = 1;
gbc.weightx = 0.2; // 比例调整
centerPanel.add(buttonPanel, gbc);
// 右侧动态面板 - 宽度增加
JPanel rightPanel = createRightPanel();
gbc.gridx = 2;
gbc.weightx = 0.4; // 比例调整
centerPanel.add(rightPanel, gbc);
mainPanel.add(centerPanel, BorderLayout.CENTER);
// 底部状态栏
JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
bottomPanel.setBorder(BorderFactory.createEtchedBorder());
bottomPanel.setBackground(new Color(230, 240, 255));
statusLabel = new JLabel("状态: 未连接");
bottomPanel.add(statusLabel);
mainPanel.add(bottomPanel, BorderLayout.SOUTH);
// 初始化控制器
controller = null;
}
private JPanel createTopPanel() {
JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
topPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 15, 0));
topPanel.setBackground(new Color(70, 130, 180));
temperatureLabel = new JLabel("当前温度: -- °C");
temperatureLabel.setFont(new Font("微软雅黑", Font.BOLD, 28));
temperatureLabel.setForeground(Color.WHITE);
topPanel.add(temperatureLabel);
return topPanel;
}
private JPanel createInputPanel() {
JPanel inputPanel = new JPanel(new GridBagLayout());
inputPanel.setBorder(BorderFactory.createTitledBorder("通信配置"));
inputPanel.setBackground(Color.WHITE);
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(5, 5, 5, 5);
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.HORIZONTAL;
int row = 0;
// 串口选择
gbc.gridx = 0;
gbc.gridy = row++;
inputPanel.add(new JLabel("串口:"), gbc);
gbc.gridx = 1;
JPanel portPanel = new JPanel(new BorderLayout(5, 0));
portComboBox = new JComboBox<>();
portComboBox.setPreferredSize(new Dimension(180, 25));
refreshPortList();
portPanel.add(portComboBox, BorderLayout.CENTER);
refreshPortButton = new JButton("刷新");
refreshPortButton.addActionListener(e -> refreshPortList());
portPanel.add(refreshPortButton, BorderLayout.EAST);
inputPanel.add(portPanel, gbc);
// 波特率
gbc.gridx = 0;
gbc.gridy = row++;
inputPanel.add(new JLabel("波特率:"), gbc);
gbc.gridx = 1;
baudRateComboBox = new JComboBox<>(new String[]{"1200", "2400", "4800", "9600","19200"});
baudRateComboBox.setSelectedIndex(0);
inputPanel.add(baudRateComboBox, gbc);
// 数据位
gbc.gridx = 0;
gbc.gridy = row++;
inputPanel.add(new JLabel("数据位"), gbc);
gbc.gridx = 1;
dateBiteComboBox = new JComboBox<>(new String[]{"6", "7", "8"});
dateBiteComboBox.setSelectedIndex(0);
inputPanel.add(dateBiteComboBox, gbc);
// 停止位
gbc.gridx = 0;
gbc.gridy = row++;
inputPanel.add(new JLabel("停止位:"), gbc);
gbc.gridx = 1;
stopBitsComboBox = new JComboBox<>(new String[]{"1", "1.5", "2"});
stopBitsComboBox.setSelectedIndex(0);
inputPanel.add(stopBitsComboBox, gbc);
// 校验方式
gbc.gridx = 0;
gbc.gridy = row++;
inputPanel.add(new JLabel("校验方式:"), gbc);
gbc.gridx = 1;
parityComboBox = new JComboBox<>(new String[]{"None", "Even", "Odd"});
parityComboBox.setSelectedIndex(0);
inputPanel.add(parityComboBox, gbc);
// 分隔线
gbc.gridx = 0;
gbc.gridy = row++;
gbc.gridwidth = 2;
inputPanel.add(new JSeparator(), gbc);
// 查询当前温度
gbc.gridx = 0;
gbc.gridy = row++;
inputPanel.add(new JLabel("初始温度:"), gbc);
gbc.gridx = 1;
JButton queryCurrentTempButton = new JButton("查询");
queryCurrentTempButton.setPreferredSize(new Dimension(80, 25));
queryCurrentTempButton.addActionListener(this::queryCurrentTemperature);
inputPanel.add(queryCurrentTempButton, gbc);
// 查询设定温度
gbc.gridx = 0;
gbc.gridy = row++;
inputPanel.add(new JLabel("设定温度:"), gbc);
gbc.gridx = 1;
JButton querySetTempButton = new JButton("查询");
querySetTempButton.setPreferredSize(new Dimension(80, 25));
querySetTempButton.addActionListener(this::querySetTemperature);
inputPanel.add(querySetTempButton, gbc);
// 分隔线
gbc.gridx = 0;
gbc.gridy = row++;
gbc.gridwidth = 2;
inputPanel.add(new JSeparator(), gbc);
// 模式选择
gbc.gridx = 0;
gbc.gridy = row++;
inputPanel.add(new JLabel("模式选择:"), gbc);
gbc.gridx = 1;
modeComboBox = new JComboBox<>(new String[]{"定值模式", "曲线模式"});
modeComboBox.setSelectedIndex(0);
inputPanel.add(modeComboBox, gbc);
// 启动控制
gbc.gridx = 0;
gbc.gridy = row++;
inputPanel.add(new JLabel("启动控制:"), gbc);
gbc.gridx = 1;
startControlButton = new JButton("启动");
startControlButton.setPreferredSize(new Dimension(100, 30));
startControlButton.setBackground(new Color(50, 150, 50));
startControlButton.setForeground(Color.WHITE);
startControlButton.addActionListener(this::startControl);
inputPanel.add(startControlButton, gbc);
return inputPanel;
}
private JPanel createButtonPanel() {
JPanel buttonPanel = new JPanel(new GridBagLayout());
buttonPanel.setBorder(BorderFactory.createTitledBorder("操作"));
buttonPanel.setBackground(Color.WHITE);
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(15, 10, 15, 10);
gbc.fill = GridBagConstraints.HORIZONTAL;
// 连接按钮
connectButton = new JButton("连接串口");
connectButton.setPreferredSize(new Dimension(150, 40));
connectButton.setFont(new Font("微软雅黑", Font.BOLD, 14));
connectButton.setBackground(new Color(70, 130, 180));
connectButton.setForeground(Color.WHITE);
connectButton.addActionListener(this::connectSerialPort);
gbc.gridy = 0;
buttonPanel.add(connectButton, gbc);
// 读取温度按钮
readButton = new JButton("读取温度");
readButton.setPreferredSize(new Dimension(150, 40));
readButton.setFont(new Font("微软雅黑", Font.BOLD, 14));
readButton.setBackground(new Color(60, 179, 113));
readButton.setForeground(Color.WHITE);
readButton.addActionListener(this::readTemperature);
gbc.gridy = 1;
buttonPanel.add(readButton, gbc);
return buttonPanel;
}
private JPanel createRightPanel() {
JPanel rightPanel = new JPanel(new BorderLayout());
rightPanel.setBorder(BorderFactory.createTitledBorder("模式配置"));
rightPanel.setBackground(Color.WHITE);
// 定值模式面板
JPanel constantModePanel = createConstantModePanel();
modeComponents.put("定值模式", constantModePanel);
// 曲线模式面板
JPanel curveModePanel = createCurveModePanel();
modeComponents.put("曲线模式", curveModePanel);
// 默认加载定值模式
rightPanel.add(modeComponents.get("定值模式"), BorderLayout.CENTER);
// 模式切换监听器
modeComboBox.addActionListener(e -> {
String selectedMode = (String) modeComboBox.getSelectedItem();
rightPanel.removeAll();
rightPanel.add(modeComponents.get(selectedMode), BorderLayout.CENTER);
rightPanel.revalidate();
rightPanel.repaint();
});
return rightPanel;
}
private JPanel createConstantModePanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBackground(Color.WHITE);
panel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridx = 0;
gbc.gridy = 0;
panel.add(new JLabel("目标温度 (°C):"), gbc);
gbc.gridx = 1;
targetTempField = new JTextField(10);
targetTempField.setText("25.5");
panel.add(targetTempField, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
panel.add(new JLabel("过渡时间 (秒):"), gbc);
gbc.gridx = 1;
transitionTimeField = new JTextField(10);
transitionTimeField.setText("30");
panel.add(transitionTimeField, gbc);
// 添加说明标签
gbc.gridx = 0;
gbc.gridy = 2;
gbc.gridwidth = 2;
JLabel infoLabel = new JLabel("<html><div style='width:250px;'>定值模式将温度稳定在设定值,过渡时间表示达到目标温度所需时间</div></html>");
infoLabel.setForeground(new Color(100, 100, 100));
panel.add(infoLabel, gbc);
return panel;
}
private JPanel createCurveModePanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBackground(Color.WHITE);
panel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(8, 5, 8, 5);
gbc.fill = GridBagConstraints.HORIZONTAL;
// 表头
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.CENTER;
panel.add(new JLabel("阶段"), gbc);
gbc.gridx = 1;
panel.add(new JLabel("目标温度 (°C)"), gbc);
gbc.gridx = 2;
panel.add(new JLabel("过渡时间 (秒)"), gbc);
gbc.gridx = 3;
panel.add(new JLabel("保持时间 (秒)"), gbc);
gbc.anchor = GridBagConstraints.WEST;
// 三阶段输入
for (int i = 0; i < 3; i++) {
gbc.gridy = i + 1;
gbc.gridx = 0;
panel.add(new JLabel("阶段 " + (i+1) + ":"), gbc);
gbc.gridx = 1;
curveTempFields[i] = new JTextField(6);
curveTempFields[i].setText("0.0");
panel.add(curveTempFields[i], gbc);
gbc.gridx = 2;
curveDurationFields[i] = new JTextField(6);
curveDurationFields[i].setText("30");
panel.add(curveDurationFields[i], gbc);
gbc.gridx = 3;
curveHoldFields[i] = new JTextField(6);
curveHoldFields[i].setText("60");
panel.add(curveHoldFields[i], gbc);
}
// 最终阶段
gbc.gridy = 4;
gbc.gridx = 0;
panel.add(new JLabel("最终目标:"), gbc);
gbc.gridx = 1;
finalTempField = new JTextField(6);
finalTempField.setText("30.0");
panel.add(finalTempField, gbc);
gbc.gridx = 2;
finalTransitionField = new JTextField(6);
finalTransitionField.setText("30");
panel.add(finalTransitionField, gbc);
// 添加说明标签
gbc.gridx = 0;
gbc.gridy = 5;
gbc.gridwidth = 4;
JLabel infoLabel = new JLabel("<html><div style='width:300px;'>曲线模式按顺序执行三个阶段,每个阶段包含升温、保持过程,最后达到最终目标温度</div></html>");
infoLabel.setForeground(new Color(100, 100, 100));
panel.add(infoLabel, gbc);
return panel;
}
// =========== 以下为功能方法 ===========
private void connectSerialPort(ActionEvent e) {
String selectedPort = (String) portComboBox.getSelectedItem();
if (selectedPort != null && controller == null) {
int baudRate = Integer.parseInt((String) baudRateComboBox.getSelectedItem());
int dateBite = Integer.parseInt((String) dateBiteComboBox.getSelectedItem());
int stopBits = getStopBitsValue();
int parity = getParityValue();
controller = new TemperatureController(this, selectedPort, baudRate, dateBite,stopBits, parity);
controller.start();
connectButton.setText("断开连接");
connectButton.setBackground(new Color(246, 115, 115)); // 红色表示断开状态
} else if (controller != null) {
// 断开连接逻辑
controller.stop();
controller = null;
setStatus("已断开连接");
connectButton.setText("连接串口");
connectButton.setBackground(new Color(70, 130, 180)); // 蓝色表示连接状态
}
}
private int getStopBitsValue() {
String stopBits = (String) stopBitsComboBox.getSelectedItem();
switch (stopBits) {
case "1": return SerialPort.ONE_STOP_BIT;
case "1.5": return SerialPort.ONE_POINT_FIVE_STOP_BITS;
case "2": return SerialPort.TWO_STOP_BITS;
default: return SerialPort.ONE_STOP_BIT;
}
}
private int getParityValue() {
String parity = (String) parityComboBox.getSelectedItem();
switch (parity) {
case "None": return SerialPort.NO_PARITY;
case "Even": return SerialPort.EVEN_PARITY;
case "Odd": return SerialPort.ODD_PARITY;
default: return SerialPort.NO_PARITY;
}
}
private void readTemperature(ActionEvent e) {
if (controller != null) {
try {
byte slaveId = 0x01;
controller.readActualTemperature(slaveId);
} catch (Exception ex) {
showError("读取温度时发生错误: " + ex.getMessage());
}
} else {
showError("请先连接串口");
}
}
private void queryCurrentTemperature(ActionEvent e) {
if (controller != null) {
try {
byte slaveId = 0x01;
controller.readActualTemperature(slaveId);
} catch (Exception ex) {
showError("查询当前温度时发生错误: " + ex.getMessage());
}
} else {
showError("请先连接串口");
}
}
private void querySetTemperature(ActionEvent e) {
if (controller != null) {
try {
byte slaveId = 0x01;
controller.readSetTemperature(slaveId);
} catch (Exception ex) {
showError("查询设定温度时发生错误: " + ex.getMessage());
}
} else {
showError("请先连接串口");
}
}
private void startControl(ActionEvent e) {
if (controller == null) {
showError("请先连接串口");
return;
}
String selectedMode = (String) modeComboBox.getSelectedItem();
try {
if ("定值模式".equals(selectedMode)) {
float targetTemp = Float.parseFloat(targetTempField.getText());
int transitionTime = Integer.parseInt(transitionTimeField.getText());
controller.startControl(targetTemp, transitionTime);
showInfo("定值模式启动: 目标温度 " + targetTemp + "°C");
} else if ("曲线模式".equals(selectedMode)) {
float[] temps = new float[4];
int[] durations = new int[4];
int[] holdTimes = new int[3];
// 获取三个阶段参数
for (int i = 0; i < 3; i++) {
temps[i] = Float.parseFloat(curveTempFields[i].getText());
durations[i] = Integer.parseInt(curveDurationFields[i].getText());
holdTimes[i] = Integer.parseInt(curveHoldFields[i].getText());
}
// 添加最终阶段参数
temps[3] = Float.parseFloat(finalTempField.getText());
durations[3] = Integer.parseInt(finalTransitionField.getText());
controller.profileManager.startCurveControl(temps, durations, holdTimes);
showInfo("曲线模式启动: 三阶段温度控制");
}
} catch (NumberFormatException ex) {
showError("请输入有效的数值: " + ex.getMessage());
} catch (IllegalArgumentException ex) {
showError("参数错误: " + ex.getMessage());
} catch (Exception ex) {
showError("启动控制时发生错误: " + ex.getMessage());
}
}
public void refreshPortList() {
portComboBox.removeAllItems();
for (SerialPort port : SerialPort.getCommPorts()) {
portComboBox.addItem(port.getSystemPortName());
}
}
public void updateTemperature(double temperature) {
SwingUtilities.invokeLater(() -> {
temperatureLabel.setText(String.format("当前温度: %.1f°C", temperature));
// 根据温度变化改变颜色
if (temperature > 35) {
temperatureLabel.setForeground(new Color(220, 20, 60)); // 高温红色
} else if (temperature < 10) {
temperatureLabel.setForeground(new Color(30, 144, 255)); // 低温蓝色
} else {
temperatureLabel.setForeground(Color.WHITE); // 正常温度白色
}
});
}
public void setStatus(String status) {
SwingUtilities.invokeLater(() ->
statusLabel.setText("状态: " + status)
);
}
private void showError(String message) {
SwingUtilities.invokeLater(() ->
JOptionPane.showMessageDialog(this, message, "错误", JOptionPane.ERROR_MESSAGE)
);
}
private void showInfo(String message) {
SwingUtilities.invokeLater(() ->
JOptionPane.showMessageDialog(this, message, "信息", JOptionPane.INFORMATION_MESSAGE)
);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
TemperatureMonitorGUI gui = new TemperatureMonitorGUI();
gui.setLocationRelativeTo(null); // 居中显示
gui.setVisible(true);
});
}
}
在我这个上面修改
最新发布