我正在开发一个图像处理软件(只是为了好玩),它的一个功能是图像大小调整选项。基本上窗口会弹出,有两个JTextArea
组件可以获得所需的图像宽度和高度,以便调整大小。如果用户需要,还有JCheckBox
用于保持宽高比。问题是。选中复选框后,用户应首先输入宽度或高度。我希望每次进行更改时,其他文本区域都会相应更新,以便保持AR。我已经开发了一些处理这个问题的代码,但它没有提供我真正想要的东西,因为我不了解我应该真正指定哪个组件的监听器。
代码:
String height, width;
if (checkBoxImage.isSelected()){
// aspect ratio = width / height
width = widthArea.getText();
height = heightArea.getText();
double aspectRatio = (double) images.get(tabbedPane.getSelectedIndex()).getWidth() / images.get(tabbedPane.getSelectedIndex()).getHeight();
/**
* to do, update width, height area
* to the closest user input
*/
if(heightArea.getText().length() != 0 && heightArea.getText().length() <= 5
&& heightArea.getText().charAt(0) != '0'){
//parsing string to integer
try{
int heightNum = Integer.parseInt(height);
int widthNum = (int) Math.round(aspectRatio * heightNum);
widthArea.setText(String.valueOf(widthNum) );
widthArea.updateUI();
frameimgSize.repaint();
}
catch(NumberFormatException e1){JOptionPane.showMessageDialog(error,e1.getMessage(),"Error", JOptionPane.ERROR_MESSAGE);}
}
//width has been entered first
else if(widthArea.getText().length() != 0 && widthArea.getText().length() <= 5 &&
widthArea.getText().charAt(0) != '0'){
try{
int widthNum = Integer.parseInt(width);
int heightNum = (int) Math.round(aspectRatio * widthNum);
heightArea.setText(String.valueOf(heightNum) );
heightArea.updateUI();
frameimgSize.repaint();
}
catch(NumberFormatException e1){JOptionPane.showMessageDialog(error,e1.getMessage(),"Error", JOptionPane.ERROR_MESSAGE);}
}
}
答案 0 :(得分:3)
首先,我不会使用JTextArea
,它意味着自由格式文本编辑(想想NotePad)。相反,您应该至少使用JTextField
但JSpinner
实际上甚至可能更好。
请查看How to Use Text Fields了解详情。
基本上,对于JTextField
,您可以使用ActionListener
和/或FocusListener
来监控字段的更改。
这个听众将倾向于在事后通知,即只有在用户完成编辑字段后才会收到通知。如果您想要实时反馈,则可以使用DocumentListener
,这将在每次修改字段的基础Document
时实时显示。
JSpinner
稍微复杂一点,因为它是一个包含编辑器和控件的组件。您可以使用ChangeListener
,这将在提交字段模型的更改时通知。这取代了之前提到的ActionListener
和FocusListener
,因此您只需要一个监听器,但不会提供实时反馈(至少,不是没有更多的工作)
答案 1 :(得分:3)
在宽度和高度字段中使用非数字值是否有效?
如果没有,请使用JSpinners
或JFormattedTextFields
代替JTextFields
。如果是这样(例如,您允许输入“单位”以及宽度和高度),您应该将DocumentListener
附加到JTextFields以监控对基础文本文档内容的更改。这是一个例子:
widthField.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
update();
}
public void removeUpdate(DocumentEvent e) {
update();
}
public void insertUpdate(DocumentEvent e) {
update();
}
// your method that handles any Document change event
public void update() {
if( aspectCheckBox1.isSelected() ) {
// parse the width and height,
// constrain the height to the aspect ratio and update it here
}
}
});
然后,您将向heightTextField添加类似的DocumentListener。
请注意,如果您使用JTextField,则需要解析其内容,读取单位(如果适用)并在用户输入无效数值的情况下处理NumberFormatExceptions。
回答有关添加处理程序的位置的问题...
当高度GUI元素的文档更改时,应发生宽度的更新。类似地,当Width GUI元素的文档更改时,应发生高度的更新。
您需要优雅地处理除以零的错误(或将输入限制为始终大于0),使用双精度执行计算,并最好使用Math.round()
来获得保留方面的最佳整数值。 / p>
即:
int calculateHeight(int width, double aspect) {
if( aspect <= 0.0 ) {
// handle this error condition
}
return (int)Math.round(width / aspect);
}
为了实际跟踪宽高比,我会将它存储在一个成员变量中,并将ActionListener
添加到JCheckBox ...因为在宽度和高度字段的每个值更改时更新目标宽高比可能会导致由于整数舍入而导致的长宽比“蠕变”。
以下是每次宽高比检查状态发生变化时跟踪方面的示例:
private double aspect = 1.0;
aspectCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
preserveAspectActionPerformed(evt);
}
});
private void preserveAspectActionPerformed(java.awt.event.ActionEvent evt) {
try {
double w = Double.parseDouble(widthField.getText());
double h = Double.parseDouble(heightField.getText());
aspect = w / h;
}
catch(NumberFormatException ex) {
// ... error occurred due to non-numeric input
// (use a JSpinner or JFormattedTextField to avoid this)
}
}
最重要的是避免为作业使用错误的输入类型:
希望对你有所帮助。