MesClientComponent.java 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. package com.mes.component;
  2. import com.mes.ui.DataUtil;
  3. import com.mes.ui.MesClient;
  4. import com.mes.ui.Oprno;
  5. import org.slf4j.Logger;
  6. import org.slf4j.LoggerFactory;
  7. import javax.swing.*;
  8. import java.awt.*;
  9. import java.awt.event.ActionEvent;
  10. import java.awt.event.ActionListener;
  11. import java.awt.event.MouseAdapter;
  12. import java.awt.event.MouseEvent;
  13. import java.util.Timer;
  14. import java.util.TimerTask;
  15. /**
  16. * OP170 单台 CNC 面板:独立轮询、独立工件数据。
  17. * <p>
  18. * 状态:0 等待上料 → 1 质量检查 → 2 加工中等下料 → 3 已下料等 OK/NG → 4 已交结果并写下料反馈
  19. */
  20. public class MesClientComponent extends JPanel {
  21. public static final Logger log = LoggerFactory.getLogger(MesClientComponent.class);
  22. public Oprno oprnoClass = new Oprno();
  23. public JTextField productSn;
  24. public JButton status_menu;
  25. public static Integer workWidth = 255;
  26. public static Integer workHeight = 320;
  27. public JButton scanBtn;
  28. public JButton resetBtn;
  29. /**
  30. * 0:等待上料完成
  31. * 1:已读码,质量检查中
  32. * 2:上料完成反馈已写,加工中,等待下料完成
  33. * 3:已见下料,等待 OK/NG 并提交 MES
  34. * 4:结果已提交且下料反馈已写,等待信号复位
  35. */
  36. public Integer work_status = 0;
  37. /** 上料完成反馈(可手动点击翻转) */
  38. public JLabel sllabel1;
  39. /** 下料完成反馈(可手动点击翻转) */
  40. public JLabel sllabel2;
  41. /** 上料完成信号(仅展示,不可点击) */
  42. public JLabel sllabelLoad;
  43. /** 下料完成信号(仅展示,不可点击) */
  44. public JLabel sllabelUnload;
  45. /** 工位状态:正常/故障 */
  46. public JLabel stationStatusLabel;
  47. /** 加工结果展示 */
  48. public JLabel resultLabel;
  49. private boolean loadEdgeHandled = false;
  50. private boolean resultHandled = false;
  51. private boolean unloadEdgeHandled = false;
  52. private boolean lastLoadComplete = false;
  53. private boolean lastUnloadComplete = false;
  54. /** 本轮是否已发送过 AQDW,避免每秒重复发 */
  55. private boolean aqdwSent = false;
  56. /** 上一次工位状态(用于故障恢复后还原状态栏) */
  57. private Boolean lastStationOk = null;
  58. public MesClientComponent(Oprno opno) {
  59. oprnoClass = opno;
  60. int w = workWidth;
  61. int h = workHeight;
  62. this.setLayout(null);
  63. this.setBackground(Color.WHITE);
  64. this.setBorder(BorderFactory.createLineBorder(Color.GRAY));
  65. int margin = Math.max(8, w / 40);
  66. int hTitle = Math.max(36, (int) Math.round(h * 0.12));
  67. int hStatus = Math.max(32, (int) Math.round(h * 0.12));
  68. int hSn = Math.max(32, (int) Math.round(h * 0.12));
  69. int hBtn = Math.max(40, (int) Math.round(h * 0.12));
  70. int hLab = Math.max(28, (int) Math.round(h * 0.1));
  71. int hFeedback = Math.max(44, (int) Math.round(h * 0.14)); // 反馈行加高,保证圆点完整显示
  72. int gap = Math.max(4, margin / 2);
  73. int y = 0;
  74. JLabel oprnoLabel = new JLabel(displayOprno(oprnoClass.getOprno()));
  75. oprnoLabel.setHorizontalAlignment(SwingConstants.CENTER);
  76. oprnoLabel.setForeground(Color.BLACK);
  77. int titleFont = Math.max(16, Math.min(36, w / 11));
  78. oprnoLabel.setFont(new Font("微软雅黑", Font.PLAIN, titleFont));
  79. oprnoLabel.setBounds(0, y, w, hTitle);
  80. this.add(oprnoLabel);
  81. y += hTitle;
  82. status_menu = new JButton("等待上料完成");
  83. status_menu.setBounds(margin, y, w - 2 * margin, hStatus);
  84. status_menu.setForeground(Color.GREEN);
  85. status_menu.addActionListener(new ActionListener() {
  86. public void actionPerformed(ActionEvent e) {
  87. }
  88. });
  89. int statusFont = Math.max(14, Math.min(22, w / 16));
  90. status_menu.setFont(new Font("微软雅黑", Font.PLAIN, statusFont));
  91. status_menu.setBackground(Color.BLACK);
  92. this.add(status_menu);
  93. y += hStatus + gap;
  94. productSn = new JTextField("");
  95. // 过长时右对齐,尾部顶满格,开头被裁切,便于看清后缀
  96. productSn.setHorizontalAlignment(SwingConstants.RIGHT);
  97. productSn.setForeground(Color.BLACK);
  98. int snFont = Math.max(14, Math.min(22, w / 16));
  99. productSn.setFont(new Font("微软雅黑", Font.PLAIN, snFont));
  100. productSn.setEditable(false);
  101. productSn.setBounds(margin, y, w - 2 * margin, hSn);
  102. productSn.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
  103. productSn.setToolTipText("点击显示二维码");
  104. productSn.setColumns(10);
  105. productSn.addMouseListener(new MouseAdapter() {
  106. @Override
  107. public void mousePressed(MouseEvent e) {
  108. // 与 op300 一致:可点;工控触摸屏上 pressed 比 clicked 更稳
  109. String sn = productSn.getText() == null ? "" : productSn.getText().trim();
  110. if (!sn.isEmpty()) {
  111. MesClient.createQRCode(sn, oprnoClass.getOprno());
  112. }
  113. }
  114. });
  115. this.add(productSn);
  116. y += hSn + gap;
  117. // 工位状态(station_status)暂不显示:现场点位未就绪时会一直报故障
  118. stationStatusLabel = new JLabel("");
  119. stationStatusLabel.setVisible(false);
  120. resultLabel = new JLabel("结果: --");
  121. resultLabel.setHorizontalAlignment(SwingConstants.CENTER);
  122. resultLabel.setFont(new Font("微软雅黑", Font.PLAIN, Math.max(12, w / 18)));
  123. resultLabel.setBounds(margin, y, w - 2 * margin, hLab);
  124. this.add(resultLabel);
  125. y += hLab + gap;
  126. scanBtn = new JButton("读码");
  127. final MesClientComponent thisComponent = this;
  128. scanBtn.addActionListener(new ActionListener() {
  129. public void actionPerformed(ActionEvent e) {
  130. thisComponent.scanBtnClick();
  131. }
  132. });
  133. try {
  134. ImageIcon raw = new ImageIcon(MesClient.class.getResource("/bg/scan_barcode.png"));
  135. Image scaled = raw.getImage().getScaledInstance(18, 18, Image.SCALE_SMOOTH);
  136. scanBtn.setIcon(new ImageIcon(scaled));
  137. } catch (Exception ignored) {
  138. }
  139. int btnFont = Math.max(14, Math.min(18, w / 14));
  140. scanBtn.setFont(new Font("微软雅黑", Font.PLAIN, btnFont));
  141. scanBtn.setMargin(new Insets(2, 4, 2, 4));
  142. scanBtn.setIconTextGap(4);
  143. int btnW = (w - 2 * margin - gap) / 2;
  144. scanBtn.setBounds(margin, y, btnW, hBtn);
  145. this.add(scanBtn);
  146. resetBtn = new JButton("刷新");
  147. resetBtn.addActionListener(new ActionListener() {
  148. public void actionPerformed(ActionEvent e) {
  149. resetBtnClick();
  150. }
  151. });
  152. try {
  153. ImageIcon raw = new ImageIcon(MesClient.class.getResource("/bg/reset_logo.png"));
  154. Image scaled = raw.getImage().getScaledInstance(18, 18, Image.SCALE_SMOOTH);
  155. resetBtn.setIcon(new ImageIcon(scaled));
  156. } catch (Exception ignored) {
  157. }
  158. resetBtn.setFont(new Font("微软雅黑", Font.PLAIN, btnFont));
  159. resetBtn.setMargin(new Insets(2, 4, 2, 4));
  160. resetBtn.setIconTextGap(4);
  161. resetBtn.setBounds(margin + btnW + gap, y, btnW, hBtn);
  162. this.add(resetBtn);
  163. y += hBtn + gap;
  164. sllabel1 = new JLabel("上料完成反馈");
  165. sllabel1.setHorizontalAlignment(SwingConstants.CENTER);
  166. sllabel1.setVerticalAlignment(SwingConstants.CENTER);
  167. sllabel1.setIcon(dot(false));
  168. sllabel1.setForeground(Color.BLACK);
  169. sllabel1.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
  170. sllabel1.setToolTipText("点击手动翻转上料完成反馈信号");
  171. sllabel1.setBounds(0, y, w / 2, hFeedback);
  172. sllabel1.addMouseListener(new MouseAdapter() {
  173. @Override
  174. public void mouseClicked(MouseEvent e) {
  175. toggleFeedback(true);
  176. }
  177. });
  178. this.add(sllabel1);
  179. sllabel2 = new JLabel("下料完成反馈");
  180. sllabel2.setHorizontalAlignment(SwingConstants.CENTER);
  181. sllabel2.setVerticalAlignment(SwingConstants.CENTER);
  182. sllabel2.setIcon(dot(false));
  183. sllabel2.setForeground(Color.BLACK);
  184. sllabel2.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
  185. sllabel2.setToolTipText("点击手动翻转下料完成反馈信号");
  186. sllabel2.setBounds(w / 2, y, w - w / 2, hFeedback);
  187. sllabel2.addMouseListener(new MouseAdapter() {
  188. @Override
  189. public void mouseClicked(MouseEvent e) {
  190. toggleFeedback(false);
  191. }
  192. });
  193. this.add(sllabel2);
  194. y += hFeedback + gap;
  195. // 上料/下料信号:只读展示 PLC→MES 完成位,不可点击
  196. sllabelLoad = new JLabel("上料信号");
  197. sllabelLoad.setHorizontalAlignment(SwingConstants.CENTER);
  198. sllabelLoad.setVerticalAlignment(SwingConstants.CENTER);
  199. sllabelLoad.setIcon(dot(false));
  200. sllabelLoad.setForeground(Color.BLACK);
  201. sllabelLoad.setToolTipText("上料完成信号(只读)");
  202. sllabelLoad.setBounds(0, y, w / 2, hFeedback);
  203. this.add(sllabelLoad);
  204. sllabelUnload = new JLabel("下料信号");
  205. sllabelUnload.setHorizontalAlignment(SwingConstants.CENTER);
  206. sllabelUnload.setVerticalAlignment(SwingConstants.CENTER);
  207. sllabelUnload.setIcon(dot(false));
  208. sllabelUnload.setForeground(Color.BLACK);
  209. sllabelUnload.setToolTipText("下料完成信号(只读)");
  210. sllabelUnload.setBounds(w / 2, y, w - w / 2, hFeedback);
  211. this.add(sllabelUnload);
  212. this.startOprnoTimer();
  213. }
  214. /** 面板标题:MES工位号 + CNC序号 */
  215. private static String displayOprno(String oprno) {
  216. if ("OP170D".equals(oprno)) {
  217. return "OP170D / CNC4";
  218. }
  219. if ("OP170E".equals(oprno)) {
  220. return "OP170E / CNC5";
  221. }
  222. if ("OP170F".equals(oprno)) {
  223. return "OP170F / CNC6";
  224. }
  225. return oprno;
  226. }
  227. private ImageIcon dot(boolean on) {
  228. try {
  229. String path = on ? "/bg/green_dot.png" : "/bg/grey_dot.png";
  230. return new ImageIcon(MesClient.class.getResource(path));
  231. } catch (Exception e) {
  232. return null;
  233. }
  234. }
  235. /** 手动翻转上料/下料完成反馈(需输入操作密码) */
  236. private void toggleFeedback(boolean load) {
  237. if (!MesClient.verifyManualPlcPassword(this)) {
  238. return;
  239. }
  240. try {
  241. String addr = load ? oprnoClass.getLoad_feedback() : oprnoClass.getUnload_feedback();
  242. boolean cur = MesClient.s7PLC.readBoolean(addr);
  243. boolean next = !cur;
  244. MesClient.s7PLC.writeBoolean(addr, next);
  245. if (load) {
  246. sllabel1.setIcon(dot(next));
  247. setMenuStatus("手动设置上料完成反馈=" + next, 0);
  248. } else {
  249. sllabel2.setIcon(dot(next));
  250. setMenuStatus("手动设置下料完成反馈=" + next, 0);
  251. }
  252. } catch (Exception ex) {
  253. log.error("手动翻转反馈失败", ex);
  254. setMenuStatus("手动写 PLC 失败", -1);
  255. }
  256. }
  257. public void refreshFeedbackIcons() {
  258. try {
  259. boolean lf = MesClient.s7PLC.readBoolean(oprnoClass.getLoad_feedback());
  260. boolean uf = MesClient.s7PLC.readBoolean(oprnoClass.getUnload_feedback());
  261. boolean lc = MesClient.s7PLC.readBoolean(oprnoClass.getLoad_complete());
  262. boolean uc = MesClient.s7PLC.readBoolean(oprnoClass.getUnload_complete());
  263. sllabel1.setIcon(dot(lf));
  264. sllabel2.setIcon(dot(uf));
  265. sllabelLoad.setIcon(dot(lc));
  266. sllabelUnload.setIcon(dot(uc));
  267. } catch (Exception ignored) {
  268. }
  269. }
  270. /** 手动读本机二维码并进入质量检查(需输入操作密码) */
  271. public void scanBtnClick() {
  272. if (!MesClient.verifyManualPlcPassword(this)) {
  273. return;
  274. }
  275. if (work_status != 0 && work_status != 1) {
  276. status_menu.setText("工件加工中,请勿重复读码");
  277. return;
  278. }
  279. try {
  280. String sn = MesClient.s7PLC.readString(oprnoClass.getProduct_sn());
  281. if (sn == null || sn.trim().isEmpty()) {
  282. setMenuStatus("扫码结果为空", -1);
  283. return;
  284. }
  285. sn = sn.trim();
  286. productSn.setText(sn);
  287. work_status = 1;
  288. loadEdgeHandled = true;
  289. aqdwSent = false;
  290. setMenuStatus("已读取工件码,等待校验", 0);
  291. } catch (Exception e) {
  292. log.error("读取 PLC 工件码失败", e);
  293. setMenuStatus("读取 PLC 失败", -1);
  294. }
  295. }
  296. public Timer oprnoTimer;
  297. public void startOprnoTimer() {
  298. if (oprnoTimer != null) {
  299. oprnoTimer.cancel();
  300. }
  301. oprnoTimer = new Timer();
  302. oprnoTimer.schedule(new TimerTask() {
  303. public void run() {
  304. try {
  305. pollOnce();
  306. } catch (Exception e) {
  307. log.error(oprnoClass.getOprno() + " 轮询异常", e);
  308. }
  309. }
  310. }, 100, 1000);
  311. }
  312. private void pollOnce() {
  313. refreshFeedbackIcons();
  314. boolean loadComplete = false;
  315. boolean unloadComplete = false;
  316. try {
  317. loadComplete = MesClient.s7PLC.readBoolean(oprnoClass.getLoad_complete());
  318. unloadComplete = MesClient.s7PLC.readBoolean(oprnoClass.getUnload_complete());
  319. } catch (Exception e) {
  320. return;
  321. }
  322. // 上料完成下降沿:仅复位本轮软件标记(不清 PLC 反馈,由 PLC 自行复位)
  323. if (lastLoadComplete && !loadComplete) {
  324. loadEdgeHandled = false;
  325. }
  326. lastLoadComplete = loadComplete;
  327. // 下料完成下降沿:仅复位软件状态;已完成的一轮清码回到 0(不清 PLC 反馈)
  328. if (lastUnloadComplete && !unloadComplete) {
  329. unloadEdgeHandled = false;
  330. if (work_status == 4) {
  331. resetCycleSoft();
  332. }
  333. }
  334. lastUnloadComplete = unloadComplete;
  335. if (work_status == 0) {
  336. // 面板尚无码时按电平触发,避免 loadEdgeHandled 卡住后 PLC 已有上料完成+码却一直“等待上料完成”
  337. String curSn = productSn.getText();
  338. boolean noSnYet = curSn == null || curSn.trim().isEmpty();
  339. if (loadComplete && (!loadEdgeHandled || noSnYet)) {
  340. String sn = "";
  341. try {
  342. sn = MesClient.s7PLC.readString(oprnoClass.getProduct_sn());
  343. } catch (Exception e) {
  344. setMenuStatus("读二维码失败", -1);
  345. return;
  346. }
  347. if (sn == null || sn.trim().isEmpty()) {
  348. setMenuStatus("二维码为空", -1);
  349. return;
  350. }
  351. sn = sn.trim();
  352. productSn.setText(sn);
  353. resultLabel.setText("结果: --");
  354. resultLabel.setForeground(Color.BLACK);
  355. loadEdgeHandled = true;
  356. resultHandled = false;
  357. unloadEdgeHandled = false;
  358. aqdwSent = false;
  359. work_status = 1;
  360. setMenuStatus("已读码,质量检查中", 0);
  361. }
  362. } else if (work_status == 1) {
  363. String sn = productSn.getText();
  364. if (sn == null || sn.trim().isEmpty()) {
  365. setMenuStatus("读码结果为空", -1);
  366. productSn.setText("");
  367. work_status = 0;
  368. loadEdgeHandled = false;
  369. return;
  370. }
  371. if (!aqdwSent) {
  372. Boolean ok = DataUtil.checkQualityByGw(MesClient.nettyClient, sn, MesClient.user20, oprnoClass.getOprno());
  373. if (ok) {
  374. aqdwSent = true;
  375. setMenuStatus("质量检查已发送,等待回复", 0);
  376. } else {
  377. setMenuStatus("质量检查消息发送失败", -1);
  378. }
  379. }
  380. // 等 MesRevice 回包后切到 status=2
  381. } else if (work_status == 2) {
  382. // 加工中:先等下料完成,再进结果提交(不下料反馈)
  383. if (unloadComplete) {
  384. work_status = 3;
  385. setMenuStatus("已下料,等待工位 OK/NG", 0);
  386. } else {
  387. setMenuStatus("加工中,等待下料", 0);
  388. }
  389. } else if (work_status == 3) {
  390. // 已见下料:等 OK/NG → 提交 MES → 再写下料反馈
  391. try {
  392. boolean okBit = MesClient.s7PLC.readBoolean(oprnoClass.getProcess_result_ok());
  393. boolean ngBit = MesClient.s7PLC.readBoolean(oprnoClass.getProcess_result_ng());
  394. if (!resultHandled && (okBit || ngBit)) {
  395. String ret = ngBit ? "NG" : "OK";
  396. String sn = productSn.getText();
  397. Boolean sent = DataUtil.sendQualityByGW(MesClient.nettyClient, sn, ret, MesClient.user20, oprnoClass.getOprno());
  398. if (sent) {
  399. resultHandled = true;
  400. final String show = ret;
  401. SwingUtilities.invokeLater(() -> {
  402. resultLabel.setText("结果: " + show);
  403. resultLabel.setForeground("NG".equals(show) ? Color.RED : new Color(0, 128, 0));
  404. });
  405. setMenuStatus("结果已提交(" + ret + "),写下料反馈", 0);
  406. writeUnloadFeedback();
  407. } else {
  408. setMenuStatus("结果提交失败,请重试", -1);
  409. }
  410. }
  411. } catch (Exception e) {
  412. log.error("读取工位结果失败", e);
  413. }
  414. } else if (work_status == 4) {
  415. setMenuStatus("下料完成反馈已写,等待复位", 0);
  416. }
  417. }
  418. /** 结果已交 MES 后再写下料完成反馈 */
  419. private void writeUnloadFeedback() {
  420. try {
  421. MesClient.s7PLC.writeBoolean(oprnoClass.getUnload_feedback(), true);
  422. unloadEdgeHandled = true;
  423. work_status = 4;
  424. setMenuStatus("结果已提交,下料反馈已写", 0);
  425. refreshFeedbackIcons();
  426. } catch (Exception e) {
  427. log.error("写下料完成反馈失败", e);
  428. setMenuStatus("写下料完成反馈失败", -1);
  429. }
  430. }
  431. /** 质量检查通过后由 MesRevice 调用:写上料完成反馈 + MKSW 记开始时间 */
  432. public void onQualityPass(String sn) {
  433. try {
  434. MesClient.s7PLC.writeBoolean(oprnoClass.getLoad_feedback(), true);
  435. DataUtil.startWorkByGw(MesClient.nettyClient, sn, MesClient.user20, oprnoClass.getOprno());
  436. work_status = 2;
  437. setMenuStatus("上料完成反馈已写,加工中", 0);
  438. refreshFeedbackIcons();
  439. } catch (Exception e) {
  440. log.error("写上料完成反馈失败", e);
  441. setMenuStatus("写上料完成反馈失败", -1);
  442. }
  443. }
  444. public void onQualityFail(String msg) {
  445. aqdwSent = false;
  446. setMenuStatus(msg + ",自动重试中…", -1);
  447. // 不写上料反馈;aqdwSent 已清,下一轮轮询会再次发质量检查
  448. }
  449. /** 工位从故障恢复后,按当前流程阶段还原状态栏文案 */
  450. private void restoreStatusAfterFault() {
  451. switch (work_status) {
  452. case 0:
  453. setMenuStatus("等待上料完成", 0);
  454. break;
  455. case 1:
  456. setMenuStatus(aqdwSent ? "质量检查已发送,等待回复" : "已读码,质量检查中", 0);
  457. break;
  458. case 2:
  459. setMenuStatus("加工中,等待下料", 0);
  460. break;
  461. case 3:
  462. setMenuStatus("已下料,等待工位 OK/NG", 0);
  463. break;
  464. case 4:
  465. setMenuStatus("结果已提交,下料反馈已写", 0);
  466. break;
  467. default:
  468. break;
  469. }
  470. }
  471. private void resetCycleSoft() {
  472. productSn.setText("");
  473. resultLabel.setText("结果: --");
  474. resultLabel.setForeground(Color.BLACK);
  475. work_status = 0;
  476. loadEdgeHandled = false;
  477. unloadEdgeHandled = false;
  478. resultHandled = false;
  479. aqdwSent = false;
  480. setMenuStatus("等待上料完成", 0);
  481. }
  482. /** 刷新复位本机面板状态(需输入操作密码):清空 SN/结果,状态回到等待上料,允许重新跑一轮 */
  483. public void resetBtnClick() {
  484. if (!MesClient.verifyManualPlcPassword(this)) {
  485. return;
  486. }
  487. productSn.setText("");
  488. resultLabel.setText("结果: --");
  489. resultLabel.setForeground(Color.BLACK);
  490. work_status = 0;
  491. loadEdgeHandled = false;
  492. resultHandled = false;
  493. unloadEdgeHandled = false;
  494. aqdwSent = false;
  495. lastStationOk = null;
  496. setMenuStatus("等待上料完成", 0);
  497. }
  498. public void setMenuStatus(String msg, int error) {
  499. SwingUtilities.invokeLater(() -> {
  500. if (error == 0) {
  501. this.status_menu.setForeground(Color.GREEN);
  502. } else {
  503. this.status_menu.setForeground(Color.RED);
  504. }
  505. this.status_menu.setText(msg);
  506. });
  507. }
  508. }