From 9d171a3c3a57ea54454d7e9d64dec213aa885a2c Mon Sep 17 00:00:00 2001
From: 张世豪 <979909237@qq.com>
Date: 星期三, 17 十二月 2025 15:26:31 +0800
Subject: [PATCH] 障碍物预览增加了序号
---
src/yaokong/RemoteControlDialog.java | 628 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 587 insertions(+), 41 deletions(-)
diff --git a/src/yaokong/RemoteControlDialog.java b/src/yaokong/RemoteControlDialog.java
index af45f17..ca29763 100644
--- a/src/yaokong/RemoteControlDialog.java
+++ b/src/yaokong/RemoteControlDialog.java
@@ -20,6 +20,17 @@
private JLabel moveJoystickValueLabel;
private JLabel turnJoystickValueLabel;
private Timer speedUpdateTimer; // 閫熷害鏇存柊瀹氭椂鍣�
+ // 鎽囨潌鎺у埗瀹氭椂鍣細鎸佺画鍙戦�佹帶鍒舵寚浠�
+ private Timer forwardControlTimer; // 鍓嶈繘/鍚庨��鎺у埗瀹氭椂鍣�
+ private Timer steeringControlTimer; // 杞悜鎺у埗瀹氭椂鍣�
+ private int targetForwardSpeed = 0; // 鐩爣鍓嶈繘/鍚庨��閫熷害
+ private int targetSteeringSpeed = 0; // 鐩爣杞悜閫熷害
+ // 鐙珛璺熻釜姣忎釜鎽囨潌鐨勫綋鍓嶉�熷害锛岄伩鍏嶇浉浜掑奖鍝�
+ private int independentForwardSpeed = 0; // 鐙珛鐨勫墠杩涢�熷害锛堜笉鍙楄浆鍚戞憞鏉嗗奖鍝嶏級
+ private int independentSteeringSpeed = 0; // 鐙珛鐨勮浆鍚戦�熷害锛堜笉鍙楀墠杩涙憞鏉嗗奖鍝嶏級
+ private List<JButton> bladeButtons = new ArrayList<>(); // 瀛樺偍鍒�鐩樻帶鍒舵寜閽紝鐢ㄤ簬娓呯悊瀹氭椂鍣�
+ private String bladeUpDefaultText = "鍒�鐩樺崌"; // 鍒�鐩樺崌鎸夐挳榛樿鏂囧瓧
+ private String bladeDownDefaultText = "鍒�鐩橀檷"; // 鍒�鐩橀檷鎸夐挳榛樿鏂囧瓧
public RemoteControlDialog(Component parent, Color themeColor, JLabel speedLabel) {
super(parent != null ? (JFrame) SwingUtilities.getWindowAncestor(parent) : null,
@@ -31,7 +42,7 @@
Control03.resetSpeeds();
Control03.sendNeutralCommandIfDebugSerialOpen();
int dialogWidth = UIConfig.DIALOG_WIDTH; // 涓庨椤靛搴︿竴鑷�
- int dialogHeight = (int) (UIConfig.DIALOG_HEIGHT / 3.0 * 0.7) + 50 + 40; // 澧炲姞40鍍忕礌
+ int dialogHeight = (int) (UIConfig.DIALOG_HEIGHT / 3.0 * 0.7) +150; // 澧炲姞90鍍忕礌锛堝師40+鏂板40+鍐嶅10锛�
initializeDialog(dialogWidth, dialogHeight);
initializeRemoteContent();
startSpeedUpdateTimer(); // 鍚姩閫熷害鏇存柊瀹氭椂鍣�
@@ -54,13 +65,69 @@
setSize(width, height);
setLocationRelativeTo(getOwner());
setResizable(false);
- getContentPane().setBackground(new Color(26, 26, 46)); // 娣辫壊鑳屾櫙
+ Container contentPane = getContentPane();
+ if (contentPane instanceof JComponent) {
+ JComponent jContentPane = (JComponent) contentPane;
+ jContentPane.setBackground(new Color(0, 0, 0, 0)); // 閫忔槑鑳屾櫙
+ jContentPane.setOpaque(false);
+ }
}
private void initializeRemoteContent() {
JPanel contentPanel = new JPanel(new BorderLayout());
contentPanel.setBorder(BorderFactory.createEmptyBorder(16, 16, 16, 16));
- contentPanel.setBackground(Color.WHITE);
+ contentPanel.setOpaque(false); // 璁剧疆涓洪�忔槑
+
+ // 鍒涘缓椤堕儴闈㈡澘锛屽寘鍚寜閽拰鏁板�兼樉绀�
+ JPanel topPanel = new JPanel(new BorderLayout());
+ topPanel.setOpaque(false);
+
+ // 鍒涘缓鎸夐挳闈㈡澘锛�4涓寜閽紝闂撮殧30鍍忕礌锛�
+ JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 30, 0));
+ buttonPanel.setOpaque(false);
+ buttonPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 8, 0)); // 搴曢儴闂磋窛8鍍忕礌
+
+ // 鎸夐挳1锛歰ff.png <-> starton.png锛屾枃瀛楋細鍚姩 <-> 鐔勭伀
+ JLabel label1 = new JLabel("鍚姩", SwingConstants.CENTER);
+ label1.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 12));
+ label1.setForeground(new Color(40, 40, 40));
+ JButton button1 = createIconButtonWithLabel("image/off.png", "image/starton.png", 27, 27,
+ label1, "鍚姩", "鐔勭伀", "POWER");
+ JPanel panel1 = createButtonWithLabel(button1, label1);
+ buttonPanel.add(panel1);
+
+ // 鎸夐挳2锛歞engoff.png <-> dengon.png锛屾枃瀛楋細寮�鐏� <-> 鍏崇伅
+ JLabel label2 = new JLabel("寮�鐏�", SwingConstants.CENTER);
+ label2.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 12));
+ label2.setForeground(new Color(40, 40, 40));
+ JButton button2 = createIconButtonWithLabel("image/dengoff.png", "image/dengon.png", 30, 30,
+ label2, "寮�鐏�", "鍏崇伅", "LIGHT");
+ JPanel panel2 = createButtonWithLabel(button2, label2);
+ buttonPanel.add(panel2);
+
+ // 鎸夐挳3锛歺ia1.png锛堝浐瀹氬浘鏍囷級锛屾枃瀛楋細鍒�鐩樺崌
+ JButton button3 = createBladeControlButton("image/xia1.png", "image/xia20.png", 30, 30, true);
+ JLabel label3 = new JLabel("鍒�鐩樺崌", SwingConstants.CENTER);
+ label3.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 12));
+ label3.setForeground(new Color(40, 40, 40));
+ button3.putClientProperty("label", label3);
+ button3.putClientProperty("defaultText", bladeUpDefaultText);
+ bladeButtons.add(button3); // 娣诲姞鍒板垪琛ㄤ互渚挎竻鐞�
+ JPanel panel3 = createButtonWithLabel(button3, label3);
+ buttonPanel.add(panel3);
+
+ // 鎸夐挳4锛歺ia2.png锛堝浐瀹氬浘鏍囷級锛屾枃瀛楋細鍒�鐩橀檷
+ JButton button4 = createBladeControlButton("image/xia2.png", "image/xia10.png", 30, 30, false);
+ JLabel label4 = new JLabel("鍒�鐩橀檷", SwingConstants.CENTER);
+ label4.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 12));
+ label4.setForeground(new Color(40, 40, 40));
+ button4.putClientProperty("label", label4);
+ button4.putClientProperty("defaultText", bladeDownDefaultText);
+ bladeButtons.add(button4); // 娣诲姞鍒板垪琛ㄤ互渚挎竻鐞�
+ JPanel panel4 = createButtonWithLabel(button4, label4);
+ buttonPanel.add(panel4);
+
+ topPanel.add(buttonPanel, BorderLayout.NORTH);
// 鍦ㄦ瘡涓憞鏉嗕笂鏂瑰垎鍒樉绀哄叾鐘舵��/鏁板�硷紙鍒嗕袱鍒楋級
JPanel valuesPanel = new JPanel(new GridLayout(1, 2, 20, 0));
@@ -80,57 +147,91 @@
valuesPanel.add(moveJoystickValueLabel);
valuesPanel.add(turnJoystickValueLabel);
- contentPanel.add(valuesPanel, BorderLayout.NORTH);
+ topPanel.add(valuesPanel, BorderLayout.CENTER);
+
+ contentPanel.add(topPanel, BorderLayout.NORTH);
// 鍒涘缓鎽囨潌闈㈡澘
JPanel joystickPanel = new JPanel(new GridLayout(1, 2, 20, 0));
joystickPanel.setOpaque(false);
// 绉诲姩鎽囨潌锛堢豢鑹蹭富棰橈級
- moveJoystick = new ModernJoystickComponent("鍓嶈繘/鍚庨��",
+ moveJoystick = new ModernJoystickComponent(" ",
new Color(46, 204, 113), true); // 缁胯壊涓婚
moveJoystick.setJoystickListener(new JoystickListener() {
@Override
public void onJoystickMoved(double x, double y) {
- // 鍙娇鐢╕杞存帶鍒跺墠杩涘悗閫�锛屽悜涓婏紙鍖楋級涓烘
- // 璁$畻骞跺洓鑸嶄簲鍏ュ埌鏁存暟閫熷害鍊硷紝姝d负鍓嶈繘锛岃礋涓哄悗閫�
+ // 鍙娇鐢╕杞存帶鍒跺墠杩涘悗閫�
+ // y鍊艰寖鍥达細-1.0锛堝悜涓婏級鍒� 1.0锛堝悜涓嬶級
+ // 璁$畻閫熷害鍊硷細鍚戜笅锛坹>0锛変负鍚庨��锛堣礋鍊硷級锛屽悜涓婏紙y<0锛変负鍓嶈繘锛堟鍊硷級
+ // 鍚庨��鍊艰寖鍥达細0 鍒� -100锛屽墠杩涘�艰寖鍥达細0 鍒� 100
int forwardVal = (int) Math.round(-y * 100.0);
// 闄愬埗鍦� [-100, 100]
forwardVal = Math.max(-100, Math.min(100, forwardVal));
- if (Math.abs(y) > 0.1) {
- applyForwardSpeed(forwardVal);
- } else {
- // 鍓嶅悗
- stopForward();
+ // 姝诲尯澶勭悊锛氬鏋滈�熷害鍊煎湪-10鍒�10涔嬮棿锛岃涓�0锛堥伩鍏嶅井灏忔姈鍔級
+ if (Math.abs(forwardVal) <= 10) {
+ forwardVal = 0;
}
- // 鏇存柊椤堕儴鏄剧ず锛堢Щ鍔ㄦ樉绀哄綋鍓嶅墠杩�/鍚庨��閫熷害锛岃浆鍚戝彇褰撳墠杞悜閫熷害浣滀负鍙傝�冿級
- int steeringVal = Control03.getCurrentSteeringSpeed();
- updateJoystickValues(forwardVal, steeringVal);
+ // 鏇存柊鐩爣閫熷害鍜岀嫭绔嬮�熷害
+ targetForwardSpeed = forwardVal;
+ independentForwardSpeed = forwardVal;
+
+ if (forwardVal != 0) {
+ // 鎽囨潌涓嶅湪姝诲尯锛屽惎鍔ㄦ寔缁彂閫佸畾鏃跺櫒
+ // 鍚庨��鏃� forwardVal 涓鸿礋鍊硷紙-100鍒�-11锛夛紝鍓嶈繘鏃� forwardVal 涓烘鍊硷紙11鍒�100锛�
+ startForwardControlTimer();
+ } else {
+ // 鎽囨潌鍦ㄦ鍖烘垨涓績浣嶇疆锛屽仠姝㈠畾鏃跺櫒
+ stopForwardControlTimer();
+ // 灏嗙嫭绔嬬殑鍓嶈繘閫熷害璁剧疆涓�0
+ independentForwardSpeed = 0;
+ // 鍙戦�佸仠姝㈡寚浠わ紙淇濇寔杞悜閫熷害涓嶅彉锛�
+ Control03.setAndSendSpeeds(independentSteeringSpeed, 0);
+ }
+
+ // 鏇存柊椤堕儴鏄剧ず锛堜娇鐢ㄧ嫭绔嬬殑閫熷害鍊硷級
+ updateJoystickValues(forwardVal, independentSteeringSpeed);
}
});
// 杞悜鎽囨潌锛堣摑鑹蹭富棰橈級
- turnJoystick = new ModernJoystickComponent("宸﹁浆/鍙宠浆",
+ turnJoystick = new ModernJoystickComponent("",
new Color(52, 152, 219), false); // 钃濊壊涓婚
turnJoystick.setJoystickListener(new JoystickListener() {
@Override
public void onJoystickMoved(double x, double y) {
- // 鍙娇鐢╔杞存帶鍒跺乏鍙宠浆鍚戯紝鍚戝彸涓烘
- // 璁$畻骞跺洓鑸嶄簲鍏ュ埌鏁存暟杞悜鍊硷紝姝d负鍙宠浆锛岃礋涓哄乏杞�
+ // 鍙娇鐢╔杞存帶鍒跺乏鍙宠浆鍚�
+ // x鍊艰寖鍥达細-1.0锛堝悜宸︼級鍒� 1.0锛堝悜鍙筹級
+ // 璁$畻杞悜鍊硷細鍚戝乏锛坸<0锛変负宸﹁浆锛堣礋鍊硷級锛屽悜鍙筹紙x>0锛変负鍙宠浆锛堟鍊硷級
+ // 宸﹁浆鍊艰寖鍥达細0 鍒� -100锛屽彸杞�艰寖鍥达細0 鍒� 100
int steeringVal = (int) Math.round(x * 100.0);
steeringVal = Math.max(-100, Math.min(100, steeringVal));
- if (Math.abs(x) > 0.1) {
- applySteeringSpeed(steeringVal);
- } else {
- // 宸﹀彸
- stopSteering();
+ // 姝诲尯澶勭悊锛氬鏋滈�熷害鍊煎湪-10鍒�10涔嬮棿锛岃涓�0锛堥伩鍏嶅井灏忔姈鍔級
+ if (Math.abs(steeringVal) <= 10) {
+ steeringVal = 0;
}
- // 鏇存柊椤堕儴鏄剧ず锛堣浆鍚戞樉绀哄綋鍓嶈浆鍚戦�熷害锛岀Щ鍔ㄦ樉绀哄綋鍓嶅墠杩涢�熷害锛�
- int forwardVal = Control03.getCurrentForwardSpeed();
- updateJoystickValues(forwardVal, steeringVal);
+ // 鏇存柊鐩爣閫熷害鍜岀嫭绔嬮�熷害
+ targetSteeringSpeed = steeringVal;
+ independentSteeringSpeed = steeringVal;
+
+ if (steeringVal != 0) {
+ // 鎽囨潌涓嶅湪姝诲尯锛屽惎鍔ㄦ寔缁彂閫佸畾鏃跺櫒
+ // 宸﹁浆鏃� steeringVal 涓鸿礋鍊硷紙-100鍒�-11锛夛紝鍙宠浆鏃� steeringVal 涓烘鍊硷紙11鍒�100锛�
+ startSteeringControlTimer();
+ } else {
+ // 鎽囨潌鍦ㄦ鍖烘垨涓績浣嶇疆锛屽仠姝㈠畾鏃跺櫒
+ stopSteeringControlTimer();
+ // 灏嗙嫭绔嬬殑杞悜閫熷害璁剧疆涓�0
+ independentSteeringSpeed = 0;
+ // 鍙戦�佸仠姝㈡寚浠わ紙淇濇寔鍓嶈繘閫熷害涓嶅彉锛�
+ Control03.setAndSendSpeeds(0, independentForwardSpeed);
+ }
+
+ // 鏇存柊椤堕儴鏄剧ず锛堜娇鐢ㄧ嫭绔嬬殑閫熷害鍊硷級
+ updateJoystickValues(independentForwardSpeed, steeringVal);
}
});
joystickPanel.add(moveJoystick);
@@ -142,6 +243,360 @@
getContentPane().add(contentPanel);
}
+ /**
+ * 鍒涘缓甯︽爣绛剧殑鎸夐挳闈㈡澘锛堝瀭鐩村竷灞�锛氭寜閽湪涓婏紝鏍囩鍦ㄤ笅锛�
+ * @param button 鎸夐挳
+ * @param label 鏍囩
+ * @return 鍖呭惈鎸夐挳鍜屾爣绛剧殑闈㈡澘
+ */
+ private JPanel createButtonWithLabel(JButton button, JLabel label) {
+ JPanel panel = new JPanel(new BorderLayout());
+ panel.setOpaque(false);
+ panel.add(button, BorderLayout.CENTER);
+ panel.add(label, BorderLayout.SOUTH);
+ panel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
+ return panel;
+ }
+
+ /**
+ * 鍒涘缓鍙垏鎹㈠浘鏍囩殑鎸夐挳锛堝甫鏍囩鏂囧瓧鍒囨崲锛�
+ * @param defaultIconPath 榛樿鍥炬爣璺緞
+ * @param clickedIconPath 鐐瑰嚮鍚庣殑鍥炬爣璺緞
+ * @param width 鍥炬爣瀹藉害
+ * @param height 鍥炬爣楂樺害
+ * @param label 鏍囩缁勪欢
+ * @param defaultText 榛樿鏂囧瓧
+ * @param clickedText 鐐瑰嚮鍚庣殑鏂囧瓧
+ * @param controlType 鎺у埗鎸囦护绫诲瀷锛�"POWER"琛ㄧず鍚姩/鐔勭伀锛�"LIGHT"琛ㄧず寮�鐏�/鍏崇伅锛宯ull琛ㄧず鏃犳帶鍒舵寚浠�
+ * @return 閰嶇疆濂界殑鎸夐挳
+ */
+ private JButton createIconButtonWithLabel(String defaultIconPath, String clickedIconPath,
+ int width, int height, JLabel label,
+ String defaultText, String clickedText, String controlType) {
+ JButton button = new JButton();
+ button.setPreferredSize(new Dimension(width, height));
+ button.setMinimumSize(new Dimension(width, height));
+ button.setMaximumSize(new Dimension(width, height));
+ button.setContentAreaFilled(false);
+ button.setBorderPainted(false);
+ button.setFocusPainted(false);
+
+ // 鍔犺浇榛樿鍥炬爣鍜岀偣鍑诲浘鏍�
+ ImageIcon defaultIcon = loadIcon(defaultIconPath, width, height);
+ ImageIcon clickedIcon = loadIcon(clickedIconPath, width, height);
+
+ if (defaultIcon != null) {
+ button.setIcon(defaultIcon);
+ }
+
+ // 浣跨敤 clientProperty 鏉ヨ窡韪寜閽姸鎬侊紙false=榛樿鍥炬爣锛宼rue=鐐瑰嚮鍥炬爣锛�
+ button.putClientProperty("isClicked", false);
+ button.putClientProperty("defaultIcon", defaultIcon);
+ button.putClientProperty("clickedIcon", clickedIcon);
+ button.putClientProperty("label", label);
+ button.putClientProperty("defaultText", defaultText);
+ button.putClientProperty("clickedText", clickedText);
+ button.putClientProperty("controlType", controlType);
+
+ // 娣诲姞鐐瑰嚮浜嬩欢锛屽垏鎹㈠浘鏍囧拰鏂囧瓧锛屽苟鍙戦�佹帶鍒舵寚浠�
+ button.addActionListener(e -> {
+ Boolean isClicked = (Boolean) button.getClientProperty("isClicked");
+ ImageIcon defaultIconRef = (ImageIcon) button.getClientProperty("defaultIcon");
+ ImageIcon clickedIconRef = (ImageIcon) button.getClientProperty("clickedIcon");
+ JLabel labelRef = (JLabel) button.getClientProperty("label");
+ String defaultTextRef = (String) button.getClientProperty("defaultText");
+ String clickedTextRef = (String) button.getClientProperty("clickedText");
+ String controlTypeRef = (String) button.getClientProperty("controlType");
+
+ if (isClicked == null || !isClicked) {
+ // 褰撳墠鏄粯璁ゅ浘鏍囷紝鍒囨崲鍒扮偣鍑诲浘鏍�
+ if (clickedIconRef != null) {
+ button.setIcon(clickedIconRef);
+ button.putClientProperty("isClicked", true);
+ }
+ // 鏇存柊鏍囩鏂囧瓧
+ if (labelRef != null && clickedTextRef != null) {
+ labelRef.setText(clickedTextRef);
+ }
+ // 鍙戦�佹帶鍒舵寚浠わ紙寮�鍚級
+ if ("POWER".equals(controlTypeRef)) {
+ boolean success = Control05.sendPowerOnIfDebugSerialOpen();
+ if (!success) {
+ showSerialClosedWarning();
+ }
+ } else if ("LIGHT".equals(controlTypeRef)) {
+ boolean success = Control07.sendLightOnIfDebugSerialOpen();
+ if (!success) {
+ showSerialClosedWarning();
+ }
+ }
+ } else {
+ // 褰撳墠鏄偣鍑诲浘鏍囷紝鍒囨崲鍥為粯璁ゅ浘鏍�
+ if (defaultIconRef != null) {
+ button.setIcon(defaultIconRef);
+ button.putClientProperty("isClicked", false);
+ }
+ // 鏇存柊鏍囩鏂囧瓧
+ if (labelRef != null && defaultTextRef != null) {
+ labelRef.setText(defaultTextRef);
+ }
+ // 鍙戦�佹帶鍒舵寚浠わ紙鍏抽棴锛�
+ if ("POWER".equals(controlTypeRef)) {
+ boolean success = Control05.sendPowerOffIfDebugSerialOpen();
+ if (!success) {
+ showSerialClosedWarning();
+ }
+ } else if ("LIGHT".equals(controlTypeRef)) {
+ boolean success = Control07.sendLightOffIfDebugSerialOpen();
+ if (!success) {
+ showSerialClosedWarning();
+ }
+ }
+ }
+ });
+
+ return button;
+ }
+
+ /**
+ * 鍒涘缓鍙垏鎹㈠浘鏍囩殑鎸夐挳
+ * @param defaultIconPath 榛樿鍥炬爣璺緞
+ * @param clickedIconPath 鐐瑰嚮鍚庣殑鍥炬爣璺緞
+ * @param width 鍥炬爣瀹藉害
+ * @param height 鍥炬爣楂樺害
+ * @return 閰嶇疆濂界殑鎸夐挳
+ */
+ private JButton createIconButton(String defaultIconPath, String clickedIconPath, int width, int height) {
+ JButton button = new JButton();
+ button.setPreferredSize(new Dimension(width, height));
+ button.setMinimumSize(new Dimension(width, height));
+ button.setMaximumSize(new Dimension(width, height));
+ button.setContentAreaFilled(false);
+ button.setBorderPainted(false);
+ button.setFocusPainted(false);
+
+ // 鍔犺浇榛樿鍥炬爣鍜岀偣鍑诲浘鏍�
+ ImageIcon defaultIcon = loadIcon(defaultIconPath, width, height);
+ ImageIcon clickedIcon = loadIcon(clickedIconPath, width, height);
+
+ if (defaultIcon != null) {
+ button.setIcon(defaultIcon);
+ }
+
+ // 浣跨敤 clientProperty 鏉ヨ窡韪寜閽姸鎬侊紙false=榛樿鍥炬爣锛宼rue=鐐瑰嚮鍥炬爣锛�
+ button.putClientProperty("isClicked", false);
+ button.putClientProperty("defaultIcon", defaultIcon);
+ button.putClientProperty("clickedIcon", clickedIcon);
+
+ // 娣诲姞鐐瑰嚮浜嬩欢锛屽垏鎹㈠浘鏍�
+ button.addActionListener(e -> {
+ Boolean isClicked = (Boolean) button.getClientProperty("isClicked");
+ ImageIcon defaultIconRef = (ImageIcon) button.getClientProperty("defaultIcon");
+ ImageIcon clickedIconRef = (ImageIcon) button.getClientProperty("clickedIcon");
+
+ if (isClicked == null || !isClicked) {
+ // 褰撳墠鏄粯璁ゅ浘鏍囷紝鍒囨崲鍒扮偣鍑诲浘鏍�
+ if (clickedIconRef != null) {
+ button.setIcon(clickedIconRef);
+ button.putClientProperty("isClicked", true);
+ }
+ } else {
+ // 褰撳墠鏄偣鍑诲浘鏍囷紝鍒囨崲鍥為粯璁ゅ浘鏍�
+ if (defaultIconRef != null) {
+ button.setIcon(defaultIconRef);
+ button.putClientProperty("isClicked", false);
+ }
+ }
+ });
+
+ return button;
+ }
+
+ /**
+ * 鍒涘缓鍥哄畾鍥炬爣鐨勬寜閽�
+ * @param iconPath 鍥炬爣璺緞
+ * @param width 鍥炬爣瀹藉害
+ * @param height 鍥炬爣楂樺害
+ * @return 閰嶇疆濂界殑鎸夐挳
+ */
+ private JButton createFixedIconButton(String iconPath, int width, int height) {
+ JButton button = new JButton();
+ button.setPreferredSize(new Dimension(width, height));
+ button.setMinimumSize(new Dimension(width, height));
+ button.setMaximumSize(new Dimension(width, height));
+ button.setContentAreaFilled(false);
+ button.setBorderPainted(false);
+ button.setFocusPainted(false);
+
+ ImageIcon icon = loadIcon(iconPath, width, height);
+ if (icon != null) {
+ button.setIcon(icon);
+ }
+
+ return button;
+ }
+
+ /**
+ * 鍒涘缓鍒�鐩樺崌闄嶆帶鍒舵寜閽紙鏀寔鐐瑰嚮鍜岄暱鎸夛級
+ * @param defaultIconPath 榛樿鍥炬爣璺緞
+ * @param clickedIconPath 鐐瑰嚮/闀挎寜鏃剁殑鍥炬爣璺緞
+ * @param width 鍥炬爣瀹藉害
+ * @param height 鍥炬爣楂樺害
+ * @param isUp true琛ㄧず鍒�鐩樺崌锛宖alse琛ㄧず鍒�鐩橀檷
+ * @return 閰嶇疆濂界殑鎸夐挳
+ */
+ private JButton createBladeControlButton(String defaultIconPath, String clickedIconPath,
+ int width, int height, boolean isUp) {
+ JButton button = new JButton();
+ button.setPreferredSize(new Dimension(width, height));
+ button.setMinimumSize(new Dimension(width, height));
+ button.setMaximumSize(new Dimension(width, height));
+ button.setContentAreaFilled(false);
+ button.setBorderPainted(false);
+ button.setFocusPainted(false);
+
+ // 鍔犺浇鍥炬爣
+ ImageIcon defaultIcon = loadIcon(defaultIconPath, width, height);
+ ImageIcon clickedIcon = loadIcon(clickedIconPath, width, height);
+
+ if (defaultIcon != null) {
+ button.setIcon(defaultIcon);
+ }
+
+ button.putClientProperty("defaultIcon", defaultIcon);
+ button.putClientProperty("clickedIcon", clickedIcon);
+ button.putClientProperty("isUp", isUp);
+ button.putClientProperty("isPressed", false);
+
+ // 闀挎寜瀹氭椂鍣�
+ Timer longPressTimer = new Timer(100, e -> { // 姣�100ms鎵ц涓�娆�
+ if (button.getClientProperty("isPressed") == Boolean.TRUE) {
+ boolean isUpButton = (Boolean) button.getClientProperty("isUp");
+ int currentHeight = Control06.getCurrentBladeHeight();
+
+ // 浣跨敤Control06鐨勬柟娉曞彂閫佹寚浠�
+ boolean success;
+ if (isUpButton) {
+ success = Control06.sendBladeUpIfDebugSerialOpen(1);
+ } else {
+ success = Control06.sendBladeDownIfDebugSerialOpen(1);
+ }
+
+ if (!success) {
+ showSerialClosedWarning();
+ } else {
+ // 鏇存柊鎸夐挳鏍囩鏄剧ず褰撳墠鏁板��
+ updateBladeButtonLabel(button);
+ }
+ }
+ });
+ longPressTimer.setInitialDelay(500); // 闀挎寜500ms鍚庡紑濮嬭繛缁彉鍖�
+ button.putClientProperty("longPressTimer", longPressTimer); // 瀛樺偍瀹氭椂鍣ㄥ紩鐢�
+
+ // 榧犳爣鎸変笅浜嬩欢
+ button.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mousePressed(MouseEvent e) {
+ button.putClientProperty("isPressed", true);
+
+ // 绔嬪嵆鍒囨崲鍥炬爣
+ ImageIcon clickedIconRef = (ImageIcon) button.getClientProperty("clickedIcon");
+ if (clickedIconRef != null) {
+ button.setIcon(clickedIconRef);
+ }
+
+ // 鐐瑰嚮鏃剁珛鍗冲鍔�/鍑忓皯10锛屼娇鐢–ontrol06鐨勬柟娉曞彂閫佹寚浠�
+ boolean isUpButton = (Boolean) button.getClientProperty("isUp");
+ boolean success;
+ if (isUpButton) {
+ success = Control06.sendBladeUpIfDebugSerialOpen(10);
+ } else {
+ success = Control06.sendBladeDownIfDebugSerialOpen(10);
+ }
+
+ if (!success) {
+ showSerialClosedWarning();
+ } else {
+ // 鏇存柊鎸夐挳鏍囩鏄剧ず褰撳墠鏁板��
+ updateBladeButtonLabel(button);
+ }
+
+ // 鍚姩闀挎寜瀹氭椂鍣�
+ longPressTimer.start();
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ button.putClientProperty("isPressed", false);
+
+ // 鍋滄闀挎寜瀹氭椂鍣�
+ longPressTimer.stop();
+
+ // 鎭㈠榛樿鍥炬爣
+ ImageIcon defaultIconRef = (ImageIcon) button.getClientProperty("defaultIcon");
+ if (defaultIconRef != null) {
+ button.setIcon(defaultIconRef);
+ }
+
+ // 鎭㈠榛樿鏂囧瓧
+ JLabel labelRef = (JLabel) button.getClientProperty("label");
+ String defaultTextRef = (String) button.getClientProperty("defaultText");
+ if (labelRef != null && defaultTextRef != null) {
+ labelRef.setText(defaultTextRef);
+ }
+ }
+ });
+
+ return button;
+ }
+
+ /**
+ * 鏇存柊鍒�鐩樻寜閽爣绛炬樉绀哄綋鍓嶆暟鍊�
+ * @param button 鎸夐挳
+ */
+ private void updateBladeButtonLabel(JButton button) {
+ JLabel labelRef = (JLabel) button.getClientProperty("label");
+ if (labelRef != null) {
+ String defaultTextRef = (String) button.getClientProperty("defaultText");
+ int currentHeight = Control06.getCurrentBladeHeight();
+ String displayText = defaultTextRef + " " + currentHeight;
+ labelRef.setText(displayText);
+ }
+ }
+
+ /**
+ * 鍔犺浇骞剁缉鏀惧浘鏍�
+ * @param iconPath 鍥炬爣璺緞
+ * @param width 鐩爣瀹藉害
+ * @param height 鐩爣楂樺害
+ * @return 缂╂斁鍚庣殑鍥炬爣
+ */
+ private ImageIcon loadIcon(String iconPath, int width, int height) {
+ try {
+ java.net.URL imgURL = getClass().getClassLoader().getResource(iconPath);
+ if (imgURL == null) {
+ // 灏濊瘯浠庢枃浠剁郴缁熷姞杞�
+ java.io.File imgFile = new java.io.File(iconPath);
+ if (imgFile.exists()) {
+ ImageIcon originalIcon = new ImageIcon(imgFile.getAbsolutePath());
+ Image scaledImage = originalIcon.getImage().getScaledInstance(width, height, Image.SCALE_SMOOTH);
+ ImageIcon scaledIcon = new ImageIcon(scaledImage);
+ scaledIcon.setDescription(iconPath);
+ return scaledIcon;
+ }
+ } else {
+ ImageIcon originalIcon = new ImageIcon(imgURL);
+ Image scaledImage = originalIcon.getImage().getScaledInstance(width, height, Image.SCALE_SMOOTH);
+ ImageIcon scaledIcon = new ImageIcon(scaledImage);
+ scaledIcon.setDescription(iconPath);
+ return scaledIcon;
+ }
+ } catch (Exception e) {
+ System.err.println("鏃犳硶鍔犺浇鍥炬爣: " + iconPath + " - " + e.getMessage());
+ }
+ return null;
+ }
+
private JPanel createStatusPanel(String label, String value, Color color) {
JPanel panel = new JPanel(new BorderLayout(0, 5));
panel.setOpaque(false);
@@ -195,14 +650,9 @@
}
private void stopForward() {
- if (Control03.getCurrentForwardSpeed() != 0) {
- boolean success = Control03.approachForwardSpeedToZero(20);
- if (!success) {
- showSerialClosedWarning();
- return;
- }
- serialWarningShown = false;
- }
+ // 灏嗙嫭绔嬬殑鍓嶈繘閫熷害璁剧疆涓�0锛屼繚鎸佽浆鍚戦�熷害涓嶅彉
+ independentForwardSpeed = 0;
+ Control03.setAndSendSpeeds(independentSteeringSpeed, 0);
}
private void applySteeringSpeed(int speed) {
@@ -225,14 +675,93 @@
}
private void stopSteering() {
- if (Control03.getCurrentSteeringSpeed() != 0) {
- boolean success = Control03.approachSteeringSpeedToZero(25);
- if (!success) {
- showSerialClosedWarning();
- return;
- }
- serialWarningShown = false;
+ // 灏嗙嫭绔嬬殑杞悜閫熷害璁剧疆涓�0锛屼繚鎸佸墠杩涢�熷害涓嶅彉
+ independentSteeringSpeed = 0;
+ Control03.setAndSendSpeeds(0, independentForwardSpeed);
+ }
+
+ /**
+ * 鍚姩鍓嶈繘/鍚庨��鎺у埗瀹氭椂鍣紝鎸佺画鍙戦�佹帶鍒舵寚浠�
+ */
+ private void startForwardControlTimer() {
+ // 濡傛灉瀹氭椂鍣ㄥ凡缁忓湪杩愯锛屽厛鍋滄瀹�
+ if (forwardControlTimer != null && forwardControlTimer.isRunning()) {
+ forwardControlTimer.stop();
}
+
+ // 鍒涘缓鏂扮殑瀹氭椂鍣紝姣�100ms鍙戦�佷竴娆℃寚浠�
+ forwardControlTimer = new Timer(100, new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ // 鎸佺画鍙戦�佺洰鏍囬�熷害鐨勬寚浠�
+ applyForwardSpeedContinuously(targetForwardSpeed);
+ }
+ });
+ forwardControlTimer.setInitialDelay(0);
+ forwardControlTimer.start();
+ }
+
+ /**
+ * 鍋滄鍓嶈繘/鍚庨��鎺у埗瀹氭椂鍣�
+ */
+ private void stopForwardControlTimer() {
+ if (forwardControlTimer != null && forwardControlTimer.isRunning()) {
+ forwardControlTimer.stop();
+ }
+ }
+
+ /**
+ * 鍚姩杞悜鎺у埗瀹氭椂鍣紝鎸佺画鍙戦�佹帶鍒舵寚浠�
+ */
+ private void startSteeringControlTimer() {
+ // 濡傛灉瀹氭椂鍣ㄥ凡缁忓湪杩愯锛屽厛鍋滄瀹�
+ if (steeringControlTimer != null && steeringControlTimer.isRunning()) {
+ steeringControlTimer.stop();
+ }
+
+ // 鍒涘缓鏂扮殑瀹氭椂鍣紝姣�100ms鍙戦�佷竴娆℃寚浠�
+ steeringControlTimer = new Timer(100, new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ // 鎸佺画鍙戦�佺洰鏍囬�熷害鐨勬寚浠�
+ applySteeringSpeedContinuously(targetSteeringSpeed);
+ }
+ });
+ steeringControlTimer.setInitialDelay(0);
+ steeringControlTimer.start();
+ }
+
+ /**
+ * 鍋滄杞悜鎺у埗瀹氭椂鍣�
+ */
+ private void stopSteeringControlTimer() {
+ if (steeringControlTimer != null && steeringControlTimer.isRunning()) {
+ steeringControlTimer.stop();
+ }
+ }
+
+ /**
+ * 鎸佺画鍙戦�佸墠杩�/鍚庨��閫熷害鎸囦护
+ */
+ private void applyForwardSpeedContinuously(int targetSpeed) {
+ // 鏇存柊鐙珛鐨勫墠杩涢�熷害
+ independentForwardSpeed = targetSpeed;
+
+ // 浣跨敤鐙珛鐨勮浆鍚戦�熷害锛堜笉鍙楀墠杩涙憞鏉嗗奖鍝嶏級锛屽彧鏇存柊鍓嶈繘閫熷害
+ // 杩欐牱鍓嶈繘鎽囨潌鐨勬搷浣滀笉浼氬奖鍝嶈浆鍚戦�熷害
+ Control03.setAndSendSpeeds(independentSteeringSpeed, independentForwardSpeed);
+ }
+
+ /**
+ * 鎸佺画鍙戦�佽浆鍚戦�熷害鎸囦护
+ */
+ private void applySteeringSpeedContinuously(int targetSpeed) {
+ // 鏇存柊鐙珛鐨勮浆鍚戦�熷害
+ independentSteeringSpeed = targetSpeed;
+
+ // 浣跨敤鐙珛鐨勫墠杩涢�熷害锛堜笉鍙楄浆鍚戞憞鏉嗗奖鍝嶏級锛屽彧鏇存柊杞悜閫熷害
+ // 杩欐牱杞悜鎽囨潌鐨勬搷浣滀笉浼氬奖鍝嶅墠杩涢�熷害
+ Control03.setAndSendSpeeds(independentSteeringSpeed, independentForwardSpeed);
}
// 鏇存柊椤堕儴鏄剧ず鐨勬憞鏉嗘暟鍊硷紙鍦� EDT 涓婅皟鐢級锛屾枃瀛楁牴鎹暟鍊兼槧灏勪负鏂瑰悜鎻忚堪
@@ -330,6 +859,15 @@
@Override
public void dispose() {
+ // 鍋滄骞舵竻鐞嗘帶鍒跺畾鏃跺櫒
+ stopForwardControlTimer();
+ stopSteeringControlTimer();
+ if (forwardControlTimer != null) {
+ forwardControlTimer = null;
+ }
+ if (steeringControlTimer != null) {
+ steeringControlTimer = null;
+ }
// 鍓嶅悗閫熷害鏇存柊瀹氭椂鍣�
if (speedUpdateTimer != null) {
speedUpdateTimer.stop();
@@ -349,6 +887,14 @@
if (turnJoystick != null) {
turnJoystick.dispose();
}
+ // 鍋滄骞舵竻鐞嗗垁鐩樻寜閽殑瀹氭椂鍣�
+ for (JButton bladeButton : bladeButtons) {
+ Timer timer = (Timer) bladeButton.getClientProperty("longPressTimer");
+ if (timer != null && timer.isRunning()) {
+ timer.stop();
+ }
+ }
+ bladeButtons.clear();
super.dispose();
}
--
Gitblit v1.10.0