I have a jTextField and I want to check whether or not its values are empty.
So far, I can do it this way:
public static JTextField checkEmpty(JTextField jTextField) {
if (jTextField.getText().equals(" ") || jTextField.getText().isEmpty()) {
return null;
} else {
return jTextField;
}
}
However, I want to do it in the manner seen below:
JTextField jTextField = new JTextField();
jTextField.checkEmpty();
This would work by returning a jTextField if it is not empty, and throw an exception or show showMessageDialog otherwise.
I'm not sure if this is possible, so any help would be appreciated.
With all that said, the actual idea is I want to create a validation class for a swing component in my project. If I can make this work then I can put it in my validation class.
Thank you.
You need to implement your own class that extend the JTextField class and add method you want.
First: you should extend JTextField like:
class MyJTextField extends JTextField
{
public MyJTextField( String defVal, int size )
{
super( defVal, size );
}
public MyJTextField()
{
super( "", size );
}
}
Second: you should add your checkEmpty() method, and you don't need the JTextField argument:
public MyJTextField checkEmpty() {
if (this.getText().equals("") ||
this.getText().isEmpty())
{
// throw your exception.
// print message or whatever you need
return null;
} else {
return this;
}
}
Then: you can use it like this:
MyJTextField jTextField = new MyJTextField();
jTextField.checkEmpty();
Related
I want to validate that data entered in a JTable cell is correct before letting the user end the editing. In the Oracle tutorial at this link
https://docs.oracle.com/javase/tutorial/uiswing/components/table.html#validtext
they make it sound very simple. An excerpt says
The automatic checking of user-entered strings occurs when the default editor attempts to create a new instance of the class associated with the cell's column. The default editor creates this instance using a constructor that takes a String as an argument. For example, in a column whose cells have type Integer, when the user types in "123" the default editor creates the corresponding Integer using code equivalent to new Integer("123"). If the constructor throws an exception, the cell's outline turns red and refuses to let focus move out of the cell. If you implement a class used as a column data type, you can use the default editor if your class supplies a constructor that takes a single argument of type String.
To test this I created the simplest case I could think of, using this class:
class CustomClass {
int value = 0;
public CustomClass(String newValue) throws NumberFormatException {
value = Integer.parseInt(newValue);
if(value<0 || value>100) throw new NumberFormatException("value out of range");
}
public String toString() {return value+"";}
}
The main idea is that if the custom class has a constructor with just a string, and a toString() method, it should work. I set up the table with CustomClass as the type for the first column. It does not produce the expected or desired result. Any attempt edit those cells results in the cell being outlined in red, and editing cannot be completed. Which is the described behavior if the entered data is bad.
This is what happens:
I do realize there are many other ways to do this. But this method was attractive because it offered the hope of using the default editor and renderer with very little extra work in the custom class (which I needed anyway). But it doesn't seem to work as advertised. I hope to be shown to be wrong ;-)
The complete program is pasted below. A couple of prints have been added to help me see what's happening, but they never print at expected time. That is, it seems the constructor and toString() method don't get called to validate and return the entered text. Anybody know why? Thanks.
-------------- complete test program -------------
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
final public class TestCodeGUI {
private JFrame frame;
private JTable table;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
TestCodeGUI window = new TestCodeGUI();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public TestCodeGUI() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 370, 168);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(10, 11, 330, 103);
frame.getContentPane().add(scrollPane);
table = new JTable();
scrollPane.setViewportView(table);
table.setModel(new DefaultTableModel(
new Object[][] {
{new CustomClass("00"), Integer.parseInt("01"), "02"},
{new CustomClass("10"), Integer.parseInt("11"), "12"},
{new CustomClass("20"), Integer.parseInt("21"), "22"},
{new CustomClass("30"), Integer.parseInt("31"), "32"},
},
new String[] {
"Column 0", "Column 1", "Column 2"
}
) {
Class[] columnTypes = new Class[] {
CustomClass.class, Integer.class, String.class
};
public Class getColumnClass(int columnIndex) {
return columnTypes[columnIndex];
}
});
System.out.println("Initialize complete");
}
}
class CustomClass {
int value = 0;
public CustomClass(String newValue) throws NumberFormatException {
System.out.println("CustomClass constructor with \"" + newValue + "\"");
value = Integer.parseInt(newValue);
if(value<0 || value>100) throw new NumberFormatException("value out of range");
}
public String toString() {
String s = value+"";
System.out.println("CustomClass toString returning \"" + s + "\"");
return s;
}
}
Take a look at the source code for the JTable class where you will find the GenericEditor class which is the default editor for the table. The stopCellEditing() method is responsible for setting the red Border.
I tried to replicate the stopCellEditing() logic in your class with the following code:
System.out.println("Initialize complete");
System.out.println(table.getDefaultEditor(Object.class));
System.out.println(table.getDefaultEditor(CustomClass.class));
Class[] argTypes = new Class[]{String.class};
java.lang.reflect.Constructor constructor;
//Class<?> type = table.getColumnClass(column);
Class<?> type = CustomClass.class;
//String s = (String)super.getCellEditorValue();
String s = "25";
try
{
//SwingUtilities2.checkAccess(constructor.getModifiers());
constructor = type.getConstructor(argTypes);
Object value = constructor.newInstance(new Object[]{s});
System.out.println(value + " : " + value.getClass());
}
catch (Exception e)
{
System.out.println(e);
//((JComponent)getComponent()).setBorder(new LineBorder(Color.red));
//return false;
}
and the code seems to work correctly since a new CustomClass object is created. However, my code can't invoke the SwingUtilities2.checkAccess(...) method, so maybe that is where the problem is?
In any case, I don't see a problem with what you are testing. I guess you need to step through the real code using a debugger so see what is happening.
Thanks to camickr for the clue to the answer. The JTable code uses introspection to access constructor and toString of the custom class, so that class must be public. Making it so fixes the problem. Thanks camickr. And thanks stackoverflow. My first question asked and aswered in 15 hours.
I have two JFrames.One Jframe has one Jtabel , when i selectedrow and press the JButton, second Jframe set string acd get text from jframe1
code in jframe1
int i = tblschdule.getSelectedRow() ;
String a = (String) tblschdule.getValueAt(i, 0) ;
String b = (String) tblschdule.getValueAt(i, 1) ;
Fisimonitoring form1 = new Fisimonitoring();
form1.acd=a;
form1.setVisible(true);
jframe2
public String acd;
code form1.acd=a; not work, String acd always null. how to solve it ?
your question is very incomplete bt here is an example to send data to another
frame
//a jframe
public class Aframe extends javax.swing.JFrame {
private Bframe bframe;
private void sendActionPerformed(java.awt.event.ActionEvent evt) {
if (bframe==null) {
bframe = new Bframe();
}
String text = jTable1.getValueAt(jTable1.getSelectedRow(),jTable1.getSelectedColumn()).toString();
bframe.setText(text);
bframe.setVisible(true);
}
}
//b jframe
public class Bframe extends javax.swing.JFrame {
public void setText(String text){
this.textField.setText(text);
}
}
in your case if you have already opened Bjframe you should make sure that same instance of Bjframe is shared by Ajframe.
It's quiet late for this answer but the solution for your problem is pretty simple.
You Need to send the value across the frame's.
Like if you are on jFrame1 and on click you are calling JFrame2
function actionPerformedOnButtonClick(){
String text = valueOfTheLabel;
new YourFrameName(text).setVisible(true);
}
And on JFrame2, You need to write a parameterized contructor like this..
public JFrame2(String textFromFrame1) {
initComponents();
}
And You can Access It on Frame2.
New to java and i am unable to see why my action listener is not working on the jcombobox. I think i have followed the other examples on the net to getSelectedItem, but nothing is happening.
FYI, my project is a unit converter (using MVC..hopefully, but that is not my priority).
Any assistance is greatly appreciated.
Thanks, Simon.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class UnitConverterView extends JFrame{
//variables and components
private static final long serialVersionUID = -4673040337179571462L;
private JComboBox<String> unitCategory;
private JTextField fromValue = new JTextField(7);
private JComboBox<String> convertFrom;
private JLabel equalsLabel = new JLabel(" = ");
private JTextField toValue = new JTextField(7);
private JComboBox<String> convertTo;
//constructor
UnitConverterView(){
//set up the view and components
JPanel unitPanel = new JPanel();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(600,300);
String[] categories = {"Length","Weight","Speed","Temperature"};
unitCategory = new JComboBox<>(categories);
String[] tofromValues = {" "};
convertFrom = new JComboBox<>(tofromValues);
convertTo = new JComboBox<>(tofromValues);
unitPanel.add(unitCategory);
unitPanel.add(fromValue);
unitPanel.add(convertFrom);
unitPanel.add(equalsLabel);
unitPanel.add(toValue);
unitPanel.add(convertTo);
this.add(unitPanel);
}
//get value to convert from
public int getMeasurement() {
return Integer.parseInt(fromValue.getText());
}
//listen for unitCategory to be selected
void addUnitCategoryListener(ActionListener listenForUnitCategory) {
unitCategory.addActionListener(listenForUnitCategory);
}
class UnitCatListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
/*String unitSelected = (String) unitCategory.getSelectedItem();
if (e.getSource() == unitCategory) {
String unitName = (String) unitCategory.getSelectedItem();
System.out.println("UnitName = " + unitName);
changeText(unitName);
}*/
JComboBox cb = (JComboBox)e.getSource();
String unitName = (String) cb.getSelectedItem();
System.out.println("UnitName = " + unitName);
}
void changeText(String name) {
toValue.setText(name);
}
}
}
You have declared a method addUnitCategoryListener() for registering listener to the combobox, but you never called this method. That's why the listener is never registered.
Add the below line at the end of your constructor, then you should be fine:
addUnitCategoryListener(new UnitCatListener());
To simply solve your problem, call the method you created to register the listener on the component. Add this to your constructor:
addUnitCategoryListener(new UnitCatListener());
However, there are a few things you'll want to know:
An ItemListener will usually do a better job than an ActionListener for a JComboBox. The previous one does not fire events if the user selects the already selected item (basically, does nothing). Usually there is nothing you need to do in these cases.
You don't need an extra method just to register the listener, you can directly add to your constructor the line
unitCategory.addActionListener(new UnitCatListener());
and remove your custom method.
The methods changeText and getMeasurement are never used.
Use parametrized types: instead of JComboBox use JComboBox<String>.
You don't need the equalsLabel as a field - a local variable will do - since you do not need to reference it anywhere later (unless you plan on changing a property of the label at runtime).
I am able to expose a private JTextField by doing this:
public void setTextField(String value) {
someTF.setText(value);
}
It would be a lot of work if I have a lot of JTextFields. I tried doing this but failed. No error it's just not setting the right value on specified JTextField.
public class SomeView {
private JTextField someTF = new JTextField(10);
...
public void initComponents() {
...
}
public void setTextField(JTextField jTF, String value) {
jTF.setText(value);
}
}
public class SomeViewTable implements ...{
public void mousePressed(MouseEvent e) {
if (e.getSource() == someButton) {
JTextField someTF = new JTextField(10);
String value = "Some Value";
SomeView sv = new SomeView();
sv.initComponents();
sv.setTextField(someTF, value);
}
}
}
Im expecting this to happen in SomeView class when I called method sameTextField
someTF.setText("Some Value");
Is this possible, what rules in java am I breaking here?
In your listener, you are creating a local variable:
JTextField someTF = new JTextField(10);
...
sv.setTextField(someTF, value);
But what you want is to set the text field of SomeView. So remove the first line, and replace the second with:
sv.setTextField(sv.someTF, value);
Now, to answer the more global question of how to expose many private JTextFields through one method, one possibility could be to assign a string ID to each of them, and store them all in a HashMap:
Map<String,JTextField> map = new HashMap<String,JTextField>();
map.put("field 1", textField1);
...
map.put("field n", textFieldn);
public void setTextField(String id, String value) {
map.get(id).setText(value);
}
Or you could simply generate getters automatically for all your fields (most IDE do that painlessly)...
I have an error for the code below. Sorry if this is too basic as I am new to java.
Basically, I cannot retrieve the String "44418" from the class CityChange.
I know the reason is because I created a new instance cc in the class MainPanel.
However I do not know any other way of doing it.
public class CityChange extends JPanel {
public CityChange() {
JButton btn1 = new JButton("London")
this.add(btn1);
btn1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
//London Yahoo Weather Code 44418
setCitySelected("44418");
}
});
}
public void setCitySelected(String citySelected) {
this.citySelected = citySelected;
}
public String getCitySelected() {
return citySelected;
}
private String citySelected;
}
public class MainPanel extends JPanel {
public MainPanel() {
CityChange cc = new CityChange();
System.out.println(cc.getCitySelected()); //returns null instead of 44418
}
}
Please give some advice. Thank you.
For timing reasons, the value has no choice but to be null.
What happens here "immediately" (at init time) is that a new CityChange object is created and its citySelected is gotten and printed. As nobody set it otherwise, it is null.
Only after firing the event (clicking the button), it gets a value, and if you print the value then, you'll see the new value.
The code setCitySelected("44418"); is only executed when you call the method public void actionPerformed(ActionEvent evt) which is not happening at the moment. This Method is only called via a Button in a GUI so you first need at least a simple Window with a Button. Here is a good example http://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html