📄 portframe.java
字号:
/** 电报发送面板 */
class SendPane extends JComponent
implements ListSelectionListener, TextFieldGroup.Checker
{
private static ResourceBundle res = JpscToolkit.getStringResourceBundle();
/** 待发送数据 */
private JTextField txtTelegram = new JTextField();
/** 名称 */
private JTextField txtName = new JTextField(6);
/** 数据格式 */
private JComboBox cbFormat = JpscToolkit.createFormatCompnent();
/** 发送按钮 */
private JButton cmdSendMsg = new UncapableButton(new SendA());
/** 定时连续发送间隔,最长10分钟 */
private JTextField txtResendInterval = new ZCIntTextField(1000, 1000 * 60 * 10, 4);
/** 定时连续发送按钮 */
private JToggleButton cmdResend = new JToggleButton();
/** 连续发送的次数,0表示一直发送 */
private int timesToResend = 0;
/** 暂存发送项到表格中的按钮 */
private JButton cmdAdd = new UncapableButton(new AddTelegramA());
/** 历史发送数据表格 */
private RWTableModel tm = new RWTableModel(new Object[]{
res.getString("table.column.name")
, res.getString("table.column.format")
, res.getString("table.column.length")
, res.getString("table.column.telegram")}, 0);
private AutoAdaptColumnWidthTable table = new AutoAdaptColumnWidthTable(tm);
/** 将存放在文件中的历史数据装入到表格中的按钮 */
private JButton cmdLoadHistory = new UncapableButton(new LoadHistoryA());
/** 保存表格中的内容到历史中的按钮 */
private JButton cmdSaveTableData = new UncapableButton(new SaveA());
/** 串口发送实现 */
private SerialPortComm portCommunicator;
/** 用于绑定发送按钮可用性的TextFieldGroup实例 */
private TextFieldGroup tfgSend;
private TextFieldGroup tfgResend;
SendPane()
{
this.constructInterface();
cmdResend.addItemListener(new ResendListener());
cmdResend.addMouseListener(new RightClickListener());
table.getSelectionModel().addListSelectionListener(this);
SelectedRowDeleteAction.enableTable(table);
}
private void constructInterface()
{
ZCFixPanel fp = new ZCFixPanel();
fp.addComToModel(JpscToolkit.createLabelForComp(("field.telegram.caption"), this.txtTelegram));
fp.addComToModel(this.txtTelegram, 5, true);
fp.newLine();
fp.addComToModel(JpscToolkit.createLabelForComp(("field.name.caption"), this.txtName));
fp.addComToModel(this.txtName, true);
fp.addComToModel(JpscToolkit.createLabelForComp(("sendPane.field.format.caption"), this.cbFormat));
fp.addComToModel(this.cbFormat);
fp.addComToModel(this.cmdSendMsg);
fp.newLine();
fp.addComToModel(this.cmdAdd, 2);
fp.addComToModel(JpscToolkit.createLabelForComp(("field.interval.caption"), this.txtResendInterval));
fp.addComToModel(this.txtResendInterval);
fp.addComToModel(this.cmdResend);
fp.newLine();
fp.addComToModel(new JScrollPane(table), 6, 1, GridBagConstraints.BOTH);
fp.newLine();
fp.addComToModel(this.cmdLoadHistory, 4);
fp.addComToModel(this.cmdSaveTableData);
this.setLayout(new BorderLayout());
this.add(fp.getSubPane());
table.setVisibleRowCount(15);
// table.setOrderable(false);
table.setShowHorizontalLines(false);
JpscToolkit.setCommandPropterties(cmdResend, "command.resend");
new TextFieldGroup(new JComponent[]{txtTelegram, txtName}, cmdAdd);
tfgSend = new TextFieldGroup(txtTelegram, cmdSendMsg);
tfgSend.addChecker(this);
tfgResend = new TextFieldGroup(new JComponent[]{txtTelegram, txtResendInterval}, cmdResend);
tfgResend.addChecker(this);
this.cbFormat.addItemListener(new FormatItemListener());
}
void setPortCommunicator(SerialPortComm spc)
{
this.portCommunicator = spc;
}
/**
* 被通知串口已经被关闭
* 串口关闭时,如果"连续发送"按钮已经按下,则迫使它弹起。
*/
void notifyPortClosed()
{
if (cmdResend.isSelected())
{
cmdResend.setSelected(false);
}
tfgSend.check();
tfgResend.check();
}
void notityPortOpened()
{
tfgSend.check();
tfgResend.check();
}
/**
* TextFieldGroup.Checker接口实现
* 判定发送和连发按钮是否可以被设置为可用
*/
public boolean toSetEnabled()
{
return this.portCommunicator != null && this.portCommunicator.isOpened();
}
/**
* 获取存储发送电报的文件
* 注意:操作系统不能创建文件名串口或并口的文件,如COM1,LPT1,NUL
*
* @return
*/
private File getHistoryFile()
{
return new File(System.getProperty("work.dir")
+ File.separator
+ JpscToolkit.getFormatedString("file.message.history",
portCommunicator.getName()));
}
/**
* 将用户选中行的数据填入“待发数据”、“名称”和“数据格式”输入组件中
* @param e 表格行选中事件
*/
public void valueChanged(ListSelectionEvent e)
{
if (!e.getValueIsAdjusting())
{
int selectedRow = table.getSelectedRow();
if (selectedRow >= 0 && tm.getRowCount() > selectedRow)
{
this.txtName.setText((String)tm.getValueAt(selectedRow, 0));
this.cbFormat.setSelectedItem(tm.getValueAt(selectedRow, 1));
this.txtTelegram.setText((String)tm.getValueAt(selectedRow, 3));
}
}
}
/**
* @todo 发送一次按钮的事件处理
*/
private class SendA extends com.zcsoft.swing.ZCAction
{
private SendA()
{
super(res.getString("command.send.caption"));
}
/**
* 事件处理实现
* @param e 事件
*/
public void actionPerformed(java.awt.event.ActionEvent e)
{
try
{
portCommunicator.sendMessage(JpscToolkit.byteArrayOfTelegram(txtTelegram.getText(),
JpscToolkit.getRadixForSelectedFormat(cbFormat)));
}
catch (Exception ex)
{
JpscToolkit.showMessageDialog((Component)e.getSource(), ex.toString());
}
}
}
/**
* @todo 连续发送电报按钮的事件处理
*/
private class ResendListener
implements ItemListener, ActionListener
{
/** 实现连续发送的定时器 */
private javax.swing.Timer resendTimer;
/** 连续发送的电报 */
private byte[] messageToResend;
/** 已经发送的次数 */
private int resentTimes = 0;
/** 连续发送按钮的初始背景色。因为连续发送过程中,按钮的背景会改变。
* 连续发送停止时,需要复原连发按钮的背景色。
*/
private Color buttonBackground;
private void stopResend()
{
if (resendTimer != null)
{
resendTimer.stop();
cmdResend.setBackground(buttonBackground);
this.setEditable(true);
if (cmdResend.isSelected())
{
cmdResend.setSelected(false);
}
}
}
private void startResend()
{
int delay = Integer.parseInt(txtResendInterval.getText());
if (resendTimer == null)
{
resendTimer = new javax.swing.Timer(delay, this);
resendTimer.setRepeats(true);
}
else
{
resendTimer.setDelay(delay);
}
try
{
messageToResend = JpscToolkit.byteArrayOfTelegram(txtTelegram.getText(),
JpscToolkit.getRadixForSelectedFormat(cbFormat));
resendTimer.start();
resentTimes = 0;
buttonBackground = cmdResend.getBackground();
this.setEditable(false);
}
catch (Exception ex)
{
JpscToolkit.showMessageDialog(cmdResend, ex.toString());
stopResend();
}
}
/**
* 设定“待发送数据”、“数据格式”和“发送间隔”组件是否可以被编辑。
* @param b true可以,false否
*/
private void setEditable(boolean b)
{
txtTelegram.setEditable(b);
txtResendInterval.setEditable(b);
cbFormat.setEnabled(b);
}
/**
* 按下时,开始重发
* 弹起时,停止重发
*
* @param e 事件
*/
public void itemStateChanged(ItemEvent e)
{
if(e.getStateChange() == ItemEvent.SELECTED)
{
this.startResend();
}
else
{
this.stopResend();
}
}
/**
* 重发时钟执行事件实现
*/
public void actionPerformed(java.awt.event.ActionEvent e)
{
//如果发送次数达到用户指定的连发次数,就停止重发
if (timesToResend > 0 && timesToResend < resentTimes)
{
stopResend();
return;
}
//用一个明显的标记表示正在发送数据。
//来回变更连发按钮的背景色
cmdResend.setBackground(cmdResend.getBackground() == buttonBackground
?buttonBackground.darker()
:buttonBackground);
try
{
portCommunicator.sendMessage(messageToResend);
resentTimes ++;
}
catch (IllegalStateException ex)
{
JpscToolkit.showMessageDialog(cmdResend, ex.getMessage());
}
}
}
/** @todo 连发按钮上鼠标右键单击处理 */
private class RightClickListener extends MouseAdapter
{
/**
* 事件处理实现
* 当用户在连续发送按钮上单击鼠标右键时,显示输入连发次数值的输入框
* @param e
*/
public void mouseReleased(MouseEvent e)
{
if (e.isPopupTrigger())
{
inputResendTimes(e);
}
}
private void inputResendTimes(MouseEvent e) throws MissingResourceException
{
String times = (String)JOptionPane.showInputDialog((Component)e.getSource()
, res.getString("resendTimes.dialog.message")
, res.getString("input.dialog.title")
, JOptionPane.QUESTION_MESSAGE, null
, null, Integer.toString(timesToResend));
if (times != null)
{
try
{
timesToResend = Integer.parseInt(times);
}
catch (NumberFormatException ex){}
}
}
}
/**
* @todo 将输入的电报放入界面表格的事件处理
*/
private class AddTelegramA extends com.zcsoft.swing.ZCAction
{
private AddTelegramA()
{
super(res.getString("command.storeIntoTable.caption"));
this.setIcon(com.zcsoft.util.ResourceLoader.createImageIcon(this.getClass(), "addItem"));
}
/**
* 根据电报的名称查找表格是否存在有相同名称的电报,如果有,则覆盖它,否则将新的电报添加到表格
* 的后面。
* @param e 事件
*/
public void actionPerformed(java.awt.event.ActionEvent e)
{
String name = txtName.getText();
Object format = cbFormat.getSelectedItem();
String telegram = txtTelegram.getText();
Integer length = new Integer(JpscToolkit.telegramLength(telegram, format));
int maybeExistRow = indexRowOf(name);
if (maybeExistRow >= 0)
{
tm.setValueAt(format, maybeExistRow, 1);
tm.setValueAt(length, maybeExistRow, 2);
tm.setValueAt(telegram, maybeExistRow, 3);
}
else
{
Vector rowData = new Vector(4);
rowData.add(name);
rowData.add(format);
rowData.add(length);
rowData.add(telegram);
tm.addRow(rowData);
maybeExistRow = tm.getRowCount() - 1;
}
table.changeSelection(maybeExistRow, 0, false, false);
}
/**
* 在界面表格中查找电报名称同指定名称相等的那一行的索引。
* 如果没有,则返回-1
*/
private int indexRowOf(String name)
{
for (int i = 0; i < tm.getRowCount(); i++)
{
if (name.equals(tm.getValueAt(i, 0)))
{
return i;
}
}
return -1;
}
}
/**
* @todo 保存表格中的电报到文件中的事件处理
*/
private class SaveA extends com.zcsoft.swing.ZCAction
{
private SaveA()
{
super(res.getString("command.save.caption"));
this.setIcon(com.zcsoft.util.ResourceLoader.createImageIcon(this.getClass(), "save"));
}
/**
* 事件处理实现
* @param e 事件
*/
public void actionPerformed(java.awt.event.ActionEvent e)
{
File outputFile = getHistoryFile();
if (outputFile.exists()
&& tm.getRowCount() == 0
&& false == ZCFixPanel.isSure((Component)e.getSource()
, JpscToolkit.getFormatedString("sureToSave.dialog.message", outputFile.getAbsolutePath())
, res.getString("sure.dialog.title")))
{
return;
}
ObjectOutputStream fos = null;
try
{
if (!outputFile.exists())
{
outputFile.createNewFile();
}
fos = new ObjectOutputStream(new FileOutputStream(outputFile.getAbsolutePath(), false));
fos.writeObject(tm.getDataVector());
fos.flush();
}
catch (IOException ex)
{
JpscToolkit.showMessageDialog((Component)e.getSource(), ex.toString());
}
finally
{
if (fos != null)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -