Error: Strange enough I get no errors.
What I'm trying to make: ( I also added // messages that explains what my code does.)
What I'm trying to make is fairly simple.
1) Fill in a name in the JTextField, press enter and the name should appear in the JTextArea. After the name is in the JTextArea the JTextField becomes empty so you can fill another name and so on there should appear a list of names in JTextArea.
2) Push the button kiesWin to make the program choose a random person from the list. (here it goes wrong)
3) Push the button resetL to reset the program so I can make a new list to choose a random winner from it.
Problem: When I Push the button Kies (Translated: Choose) it should choose a random name from the ArrayList and show the random name in the JTextField textvak2. But when I push the button Kies the program does nothing. And it should show me the random chosen name from the ArrayList.
This is the class that doesn't works properly: (I Think)
// This is the button that chooses a random name from the ArrayList.
// The random chosen name should appear in the JTextField textvak2. (but it doesn't)
// This is also the part where it goes wrong at the moment.
class Kies extends OnthoudNaam implements ActionListener {
public void actionPerformed( ActionEvent e ) {
Random r = new Random();
if (lijst.size() > 0) {
int n = r.nextInt(lijst.size());
Naam kiesNaam = lijst.get(n);
textvak2.setText(kiesNaam.getIngevoerdNaam());
}
}
}
For in case you need the whole code:
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
// Main method to make the frame.
public class Loterij3 extends JFrame {
public static void main( String args[] ) {
JFrame frame = new Loterij3();
frame.setExtendedState( frame.MAXIMIZED_BOTH );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setTitle( "My Lottery!" );
frame.setContentPane( new Paneel() );
frame.setVisible( true );
}
}
// This is the Panel that goes into the frame.
class Paneel extends JPanel {
private Boven boven;
JTextArea textvak1;
JTextField textvak2;
OnthoudNaam onthoudNaam = new OnthoudNaam();
JTextField invoervak1; // JTextField from class Boven.
public Paneel() {
setLayout( new BorderLayout() ); // using border Layout.
setBackground( Color.LIGHT_GRAY );
boven = new Boven();
textvak1 = new JTextArea();
add( new JScrollPane( textvak1 ) );
textvak1.setBackground( Color.WHITE );
textvak2 = new JTextField();
textvak2.setHorizontalAlignment(JTextField.CENTER);
add( boven, BorderLayout.NORTH ); // Where the class Boven should be.
add( textvak1, BorderLayout.CENTER );
add( textvak2, BorderLayout.SOUTH );
}
// This is the class Boven (Translation up or upper).
// This is where the JButtons, JTextField and JLabels are.
public class Boven extends JPanel {
JButton kiesWin, resetL;
JLabel label1;
public Boven() {
setBackground( Color.LIGHT_GRAY );
setLayout( new GridLayout( 1, 4, 100, 5 ) ); // using GridLayout.
Border border =
BorderFactory.createEmptyBorder( 10, 10, 10, 10 );
setBorder( border );
kiesWin = new JButton("Kies een Winnaar!");
kiesWin.addActionListener( new Kies() );
resetL = new JButton("Reset alles");
resetL.addActionListener( new Reset() );
label1 = new JLabel("Voer Persoon in en druk op enter: ", JLabel.RIGHT);
invoervak1 = new JTextField( 20 );
invoervak1.addActionListener( new InvoerVakHandler() );
add( label1 );
add( invoervak1 );
add( kiesWin );
add( resetL );
}
}
// The class Naam (translation = name).
// This is what the ArrayList should remember
// In other words ArrayList should remember the Names I put in the JTextField.
class Naam {
private String ingevoerdNaam;
public Naam( String ingevoerdNaam) {
this.ingevoerdNaam = ingevoerdNaam;
}
public String getIngevoerdNaam() {
return ingevoerdNaam;
}
public String toString() {
return ingevoerdNaam;
}
}
// This is my ArrayList,
// This should remember the names I type in the JTextField.
class OnthoudNaam extends JPanel {
protected ArrayList<Naam> lijst;
public OnthoudNaam() {
lijst = new ArrayList<Naam>();
}
public void voegNaamToe(Naam x ) {
lijst.add(x);
}
public String toString() {
StringBuffer buffer = new StringBuffer();
for(Naam x : lijst ) {
buffer.append( x );
buffer.append( "\n" );
}
return buffer.toString();
}
}
// This is the JTextField where I enter the names.
// The Name I fill in the JTextField should be remembered by the ArrayList.
// The Name I fill in should be put in the JTextArea.
public class InvoerVakHandler implements ActionListener {
public void actionPerformed( ActionEvent e ) {
String invoer = invoervak1.getText();
Naam Naam = new Naam( invoer );
onthoudNaam.voegNaamToe( Naam );
textvak1.setText( onthoudNaam.toString() );
invoervak1.setText( "" );
}
}
// This is the button that chooses a random name from the ArrayList.
// This is also the part where it goes wrong at the moment.
class Kies extends OnthoudNaam implements ActionListener {
public void actionPerformed( ActionEvent e ) {
Random r = new Random();
if (lijst.size() > 0) {
int n = r.nextInt(lijst.size());
Naam kiesNaam = lijst.get(n);
textvak2.setText(kiesNaam.getIngevoerdNaam());
}
}
}
// This should become the button that resets everything so you can start over.
class Reset implements ActionListener {
public void actionPerformed( ActionEvent e ) {
}
}
}
Random#nextInt requires a positive number but the initial size of the List lijst is 0 hence the Exception
The docs clearly state this
Throws:
IllegalArgumentException - if n is not positive
Check that there are entries in the List first.
if (lijst.size() > 0) {
int n = r.nextInt(lijst.size());
Naam kiesNaam = lijst.get(n);
textvak2.setText(kiesNaam.getIngevoerdNaam());
}
Aside: Rather than casting the object from the List, extract the Naam object and use its getIngevoerdNaam method.
Remember too The debugger is your friend
Related
package helloworld;
import javax.swing.*;
import java.awt.event.*;
public class helloworld extends JFrame{
public static void main( String args[] ){
JFrame frame = new helloworld();
frame.setSize( 400, 200 );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setTitle( "HelloWorld" );
JPanel panel = new Panel();
frame.setContentPane( panel );
frame.setVisible( true );
}
}
class Panel extends JPanel {
private JButton button, resetbutton;
private JTextField textfield;
public Panel(){
button = new JButton( "click" );
button.addActionListener( new ButtonHandler() );
resetbutton = new JButton( "erase" );
resetbutton.addActionListener( new ResetbuttonHandler() );
textfield = new JTextField( 10 );
add( button );
add( textfield );
add( resetbutton );
}
class ButtonHandler implements ActionListener{
public void actionPerformed( ActionEvent e ){
textfield.setText( "you clicked" );
}
}
class ResetbuttonHandler implements ActionListener{
public void actionPreformed( ActionEvent e ){
textfield.setText( "" );
}
}
}
I just set up some basic code to learn a bit more about java. But I have a problem regarding my button classes.
The error says the following: The type Panel.ResetbuttonHandler must implement the inherited abstract method ActionListener.actionPerformed(ActionEvent) Previously I also had this problem with the ButtonHandler class, somehow I solved this problem, but the ResetbuttonHandler still shows the same error, and I couldn't figure out what the differences between them were.I also tried to #Override them, but that didn't work. I've got a book about java (that is also where I'm learning from), and they do this in the exact same way. Even searched the whole internet, still didn't find the solution. I hope that someone can help me with this problem!
Please correct spelling of actionPreformed method to actionPerformed
class ResetbuttonHandler implements ActionListener{
public void actionPerformed( ActionEvent e ){
textfield.setText( "" );
}
}
I'm looking to do something which may be impossible; in Java (1.6 running on Windows 7, since this is platform-dependent), I want to have a window appear over another window, but not steal focus from the triggering component. In the example attached below, I'd like to be able to be able to click on the text field, have the new pop up appear in front, but maintain focus on the text field. What I instead notice is that I get the panel to the front, but do not get focus on the text field again.
I'm primarily wondering if this is possible (normally the front Window has focus in Windows, so I'm leaning towards probably not). If not, but someone has opinions on a good workaround, I'm open ears.
Example:
public class PopUpExample
{
// Global toolkit listener.
enum PopUp
{
INSTANCE;
private PopUpWindow m_popUp;
private JTextComponent m_textComponent;
public void initialize(PopUpWindow p)
{
m_popUp = p;
Toolkit.getDefaultToolkit().addAWTEventListener( new AWTEventListener()
{
public void eventDispatched(AWTEvent e)
{
// Ensure event is a focus gain event.
if (( e instanceof FocusEvent )
&& ((FocusEvent)e).getID()==FocusEvent.FOCUS_GAINED)
{
// If it is on a text field, make the pop up appear, but maintain focus on the text field
if ( (e.getSource() instanceof JTextComponent) )
{
m_textComponent = (JTextComponent)e.getSource();
// FIXME Code below here should set the button on top, yet leave the text field with focus.
m_popUp.setAlwaysOnTop( true );
m_popUp.setFocusable( false );
m_popUp.setVisible( true );
m_textComponent.requestFocus();
// end FIXME
}
// Otherwise, make the pop up disappear (if it isn't the pop up itself).
else if (((JComponent)e.getSource()).getRootPane().getComponent(0) instanceof PopUpWindow)
{
m_popUp.setVisible( false );
}
}
}
}, AWTEvent.FOCUS_EVENT_MASK);
}
}
// Pop up window that isn't focusable
class PopUpWindow extends JFrame
{
public PopUpWindow()
{
super();
BorderLayout layout = new BorderLayout();
this.setLayout( layout );
this.setMinimumSize( new Dimension( 100, 100 ) );
JButton button = new JButton("WantOnFront");
button.setFocusable( false );
this.add( button, BorderLayout.CENTER );
this.setFocusable( false );
}
}
// Main application window.
class GuiWindow extends JFrame
{
public GuiWindow()
{
super();
BorderLayout layout = new BorderLayout();
this.setLayout( layout );
this.setMinimumSize( new Dimension( 400, 400 ) );
JButton button = new JButton("defaultFocusButton");
this.add( button, BorderLayout.CENTER );
JTextField textField = new JTextField("WantToMaintainFocusWhenClicked");
this.add( textField, BorderLayout.SOUTH );
}
}
// Setup code
public PopUpExample()
{
new GuiWindow().setVisible( true );
PopUp.INSTANCE.initialize( new PopUpWindow() );
}
public static void main( String[] args )
{
new PopUpExample();
}
}
have the new pop up appear in front, but maintain focus on the text field.
JDialog dialog = new JDialog(...);
dialog.setFocusableWindowState( false );
...
dialog.setVisible( true );
I'm building an Typing program and i have made an list with exercises to type
public class OefeningenListModel extends AbstractListModel {
private JComboBox time; //time combo box to select time
public OefeningenListModel() {
oefeningen = new ArrayList<Oefening>();
Oefening o1 = new Oefening("1", "Oefening HJ");
Oefening o2 = new Oefening("2", "Oefening KL");
Oefening o3 = new Oefening("3", "Oefening JH");
oefeningen.add(o1);
oefeningen.add(o2);
oefeningen.add(o3);
}
those exercises are shown in an jTable on my frame
public BasisSchermm() {
initComponents();
jList1.setModel(new OefeningenListModel());
and on this frame there is even add an jButton
now is my question:
i want to add a actionperformed on this button when a exercise is selected in the table and you click to button(when the exercise is selected) you move to a new frame to type the exercise but i have no idea how i can do this
to get the selected item in your JList you could do like this:
// Get the index of the selected item
int selectedIndex = jList1.getSelectedIndex();
// Get the selected item from the model
Object sel = jList1.getModel().getElementAt(selectedIndex);
or if needed you could cast it to the type you need:
Oefening selectedItem = (Oefening) list.getModel().getElementAt(selectedIndex);
to add the action listener:
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
if (xItemIsSelected) {
//open 'x' frame
new xFrame().show();
}
if (yItemIsSelected) {
//open 'y' frame
new yFrame().show();
}
}
};
//add the listener to the button
button.addActionListener(actionListener);
To put you in the right direction a small piece of sample code (minus the imports) which creates a JFrame where the contents of the main panel is controlled by the selection in the JList. The example shows how to react on selection changes in the JList, and shows an alternative for constantly opening new windows, which is a terrible user experience.
public class ListSelectionExample {
private static String[] MODEL_CONTENTS = new String[]{"String1","String2","String3"};
public static void main( String[] args ) throws InvocationTargetException, InterruptedException {
EventQueue.invokeAndWait( new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame( "TestFrame" );
//create a JList
final JList list = new JList( );
DefaultListModel listModel = new DefaultListModel();
for ( String modelContents : MODEL_CONTENTS ) {
listModel.addElement( modelContents );
}
list.setModel( listModel );
list.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
//use a CardLayout to switch between different labels
final CardLayout cardLayout = new CardLayout();
final JPanel contentPane = new JPanel( cardLayout );
for ( String label_content : MODEL_CONTENTS ) {
contentPane.add( new JLabel( label_content ), label_content );
}
cardLayout.show( contentPane, MODEL_CONTENTS[0] );
//when the list selection is changed, switch the contents of the JPanel
list.addListSelectionListener( new ListSelectionListener() {
#Override
public void valueChanged( ListSelectionEvent aListSelectionEvent ) {
int selectedIndex = list.getSelectedIndex();
String modelElement = ( String ) list.getModel().getElementAt( selectedIndex );
cardLayout.show( contentPane, modelElement );
}
} );
frame.getContentPane().add( list, BorderLayout.EAST );
frame.getContentPane().add( contentPane, BorderLayout.CENTER );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.pack();
frame.setVisible( true );
}
} );
}
}
I have a JTable which is loaded from a data-structure using table model.The data-structure is of the format NavigableMap<Float,NavigableMap<Float,Boolean>>.An example data is:
Table Format:
Range f1,v1 f2,v2 f3,v3 f4,v4
12.1-30.2 30,true 32,false 45,true 50,false
30.2-45.6 30,true 32.4,true 45,true 50.1,true
The above data format is represented in the DS as
DS Format:
Key Value
12.1 <<30,true>,<32,false>,<45,true>,<50,false>>
30.2 <<30,true>,<32.4,true>,<45,true>,<50.1,true>>
45.6 null
I have managed to represent the above given data in Jtable using table-model.Once the data is loaded from the DS to the table I have to allow user edit.Now this is where I have problem.My doubt is whether is should keep the data structure synchronized with the changes in the table or should i recreate the DS from the table once the user finish editing and then replace it with the old one.
More over I need to validate the data(for example from above - Suppose the user want's to edit the value 30.1.He should only be allowed to enter values between 12.1 and 45.6.Since data the tables are string's (once loaded) I'm planning to use regex and key-listener and consume all user key presses which doesn't match the regex and values which doesn't come within the range.I'm not sure is this is a good idea or what are implications.I would like to get some suggestions on this.
I would recreate your DS once the user is finised editing the table.
You can always create a custom editor to display a popup dialog where you have two separate text fields for each value of the range. Then you can edit each field as a double value within your specified range and recreate the formatted string before saving it to the model. Here's an old example I have lying around to get you started:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
/*
* The editor button that brings up the dialog.
*/
//public class TablePopupEditor extends AbstractCellEditor
public class TablePopupEditor extends DefaultCellEditor
implements TableCellEditor
{
private PopupDialog popup;
private String currentText = "";
private JButton editorComponent;
public TablePopupEditor()
{
super(new JTextField());
setClickCountToStart(2);
// Use a JButton as the editor component
editorComponent = new JButton();
editorComponent.setBackground(Color.white);
editorComponent.setBorderPainted(false);
editorComponent.setContentAreaFilled( false );
// Set up the dialog where we do the actual editing
popup = new PopupDialog();
}
public Object getCellEditorValue()
{
return currentText;
}
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
System.out.println("run");
popup.setText( currentText );
// popup.setLocationRelativeTo( editorComponent );
Point p = editorComponent.getLocationOnScreen();
popup.setLocation(p.x, p.y + editorComponent.getSize().height);
popup.show();
fireEditingStopped();
}
});
currentText = value.toString();
editorComponent.setText( currentText );
return editorComponent;
}
/*
* Simple dialog containing the actual editing component
*/
class PopupDialog extends JDialog implements ActionListener
{
private JTextArea textArea;
public PopupDialog()
{
super((Frame)null, "Change Description", true);
textArea = new JTextArea(5, 20);
textArea.setLineWrap( true );
textArea.setWrapStyleWord( true );
KeyStroke keyStroke = KeyStroke.getKeyStroke("ENTER");
textArea.getInputMap().put(keyStroke, "none");
JScrollPane scrollPane = new JScrollPane( textArea );
getContentPane().add( scrollPane );
JButton cancel = new JButton("Cancel");
cancel.addActionListener( this );
JButton ok = new JButton("Ok");
ok.setPreferredSize( cancel.getPreferredSize() );
ok.addActionListener( this );
JPanel buttons = new JPanel();
buttons.add( ok );
buttons.add( cancel );
getContentPane().add(buttons, BorderLayout.SOUTH);
pack();
getRootPane().setDefaultButton( ok );
}
public void setText(String text)
{
textArea.setText( text );
}
/*
* Save the changed text before hiding the popup
*/
public void actionPerformed(ActionEvent e)
{
if ("Ok".equals( e.getActionCommand() ) )
{
currentText = textArea.getText();
}
textArea.requestFocusInWindow();
setVisible( false );
}
}
public static void main(String[] args)
{
String[] columnNames = {"Item", "Description"};
Object[][] data =
{
{"Item 1", "Description of Item 1"},
{"Item 2", "Description of Item 2"},
{"Item 3", "Description of Item 3"}
};
JTable table = new JTable(data, columnNames);
table.getColumnModel().getColumn(1).setPreferredWidth(300);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane(table);
// Use the popup editor on the second column
TablePopupEditor popupEditor = new TablePopupEditor();
table.getColumnModel().getColumn(1).setCellEditor( popupEditor );
JFrame frame = new JFrame("Popup Editor Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add( scrollPane );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
}
Problem:
I have the following JList which I add to the textPane, and show it upon the caret moving. However, after double clicking on the Jlist element, the text gets inserted, but the caret is not appearing on the JTextPane.
This is the following code:
listForSuggestion = new JList(str.toArray());
listForSuggestion.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
listForSuggestion.setSelectedIndex(0);
listForSuggestion.setVisibleRowCount(visibleRowCount);
listScrollPane = new JScrollPane(listForSuggestion);
MouseListener mouseListener = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent mouseEvent) {
JList theList = (JList) mouseEvent.getSource();
if (mouseEvent.getClickCount() == 2) {
int index = theList.locationToIndex(mouseEvent.getPoint());
if (index >= 0) {
Object o = theList.getModel().getElementAt(index);
//System.out.println("Double-clicked on: " + o.toString());
//Set the double clicked text to appear on textPane
String completion = o.toString();
int num= textPane.getCaretPosition();
textPane.select(num, num);
textPane.replaceSelection(completion);
textPane.setCaretPosition(num + completion.length());
int pos = textPane.getSelectionEnd();
textPane.select(pos, pos);
textPane.replaceSelection("");
textPane.setCaretPosition(pos);
textPane.moveCaretPosition(pos);
}
}
theList.clearSelection();
Any idea on how to "de-focus" the selection on the Jlist, or make the caret appear on the JTextPane after the text insertion?
I'll elaborate more if this is not clear enough. Please help, thanks!
Have a look and play around with the focus-methods in JComponent
Specifically grabFocus and requestFocusInWindow
What happens for instance, if you add textPane.grabFocus() after textPane.moveCaretPosition(pos);?
Although not related to your problem, you may want to check out the List Action, which attempts to handle this type of request in a more general way.
Edit:
Here is my simple SSCCE that shows invokeLater is not required:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ListActionTest
{
public static void main(String[] args)
throws Exception
{
final JTextField textField = new JTextField();
Action displayAction = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
JList list = (JList)e.getSource();
System.out.println(list.getSelectedValue());
textField.setText(list.getSelectedValue().toString());
textField.requestFocusInWindow();
}
};
String[] data = { "zero", "one", "two", "three", "four", "five" };
JList list = new JList( data );
ListAction la = new ListAction(list, displayAction);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.getContentPane().add( new JScrollPane(list) );
frame.add(textField, BorderLayout.SOUTH);
frame.setSize(400, 100);
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
}