Reputation: 13
First time posting. I feel this should be rather straight-forward, but after searching and trying, I've been left without a solution. I re-created my problem in a very simple MVC program - it's behaving the same in both this sample application and in my actual application; I'm clearly making the same mistake in both places.
In my Java desktop application, I have the GUI code in a "View" class. This class is strictly responsible for the appearance of the GUI, ensuring all viewable objects are laid out on the screen/window. The "Controller" is handling all the program flow, and is responsible for listening for the user events, such as a button click, and then calling the necessary View methods to either retrieve or put data from/to the GUI.
The classes, below, do this in a very simple way - all it does is draw a small JFrame window containing a JPanel with 4 objects, 3 JButtons and a JTextField. When any of the 3 buttons is pressed, the number of that button, 1, 2, or 3, is to be displayed in the text field. Only, the field isn't updating. I have a method in the View that calls the repaint() and revalidate() methods of the JFrame, called from the controller right after it updates the text field after a button press. I have a print statement that writes the text to the console, so I know that part works. I also believe the updating of the text field works as I have a message dialog display its value. My understanding is JFrame.repaint(); is supposed to repaint the frame and all its descendants (objects within), it just, isn't.
Thanks in advance for helping. Here's my sample code:
Model.java (currently empty)
package com.techbybryan;
public class Model {
}
View.java
package com.techbybryan;
import javax.swing.*;
import java.awt.*;
public class View {
JButton button1 = new JButton( "One" );
JButton button2 = new JButton( "Two" );
JButton button3 = new JButton( "Three" );
JTextField jTextField = new JTextField();
JPanel jPanel = new JPanel();
JFrame jFrame = new JFrame( "Gui Test" );
public View(){
jPanel.add( button1 );
jPanel.add( button2 );
jPanel.add( button3 );
jPanel.add( jTextField );
jFrame.add( jPanel );
jFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
jFrame.setSize(new Dimension( 500, 100 ) );
jFrame.setLocationRelativeTo( null );
jFrame.setResizable( false );
jFrame.setVisible( true );
}
public JButton getButton1() {
return button1;
}
public void setButton1( JButton button1 ) {
this.button1 = button1;
}
public JButton getButton2() {
return button2;
}
public void setButton2( JButton button2 ) {
this.button2 = button2;
}
public JButton getButton3() {
return button3;
}
public void setButton3( JButton button3 ) {
this.button3 = button3;
}
public JTextField getjTextField() {
return jTextField;
}
public void setJTextField( JTextField jTextField ) {
this.jTextField = jTextField;
}
public void repaint(){
jFrame.revalidate();
jFrame.repaint();
JOptionPane.showMessageDialog( null, jTextField );
}
}
Controller.java
package com.techbybryan;
import javax.swing.*;
public class Controller {
Model model;
View view;
Controller controller;
public Controller( Model model, View view ){
this.model = model;
this.view = view;
}
public void init(){
view.getButton1().addActionListener( e -> setOutputText( "One" ) );
view.getButton2().addActionListener( e -> setOutputText( "Two" ) );
view.getButton3().addActionListener( e -> setOutputText( "Three" ) );
}
public void setOutputText( String textToDisplay ){
System.out.println( textToDisplay );
view.setJTextField( new JTextField( textToDisplay ) );
view.repaint();
}
}
GuiText.java
package com.techbybryan;
public class GuiTest {
public static void main(String[] args) {
Model model = new Model();
View view = new View();
Controller controller = new Controller( model, view );
controller.init( );
}
}
Thank you so much for any constructive advice you may have; I appreciate your feedback.
Upvotes: 1
Views: 268
Reputation: 285405
This code in your controller is not right:
view.setJTextField( new JTextField( textToDisplay ) );
The controller should not be adding components to the view, but rather that method, the actionlistener, should be changing the state of the model, something that you can't do since your model class is inexplicably empty.
In short, you're doing things backwards -- you should get your model working first, and then wire the control and the view to work with the model first and foremost. Your model should notify the view when it changes (a PropertyChangeListener would work well here), and then the view should update the display in the currently displayed JTextField (not adding a new JTextField --sorry to be blunt, but that's plum crazy), based on the model's state.
Also, get rid of all those repaints and revalidates as that code will not help your basic problem and is unnecessary.
Note also that I would get rid of this code:
public void setJTextField( JTextField jTextField ) {
this.jTextField = jTextField;
}
Instead do something more like:
public void setJTextFieldText(String text) {
this.jTextField.setText(text);
}
don't go adding components unnecessarily but instead change the state of the components that you already have
Upvotes: 2