java observer GUI not updating - java

I managed to send an update to my observer (textarea)
when I logged textarea.getText() the result is my updated message.
but the GUI is not updating (still blank). What is the problem?
my observer
public void update(Observable o, Object data){
jTextArea2.setText((String)data);
}
my observable
public class Login extends javax.swing.JFrame
{
private static final long serialVersionUID = 2736805471773039923L;
final ObjectObservable observable;
public Login()
{
observable = new ObjectObservable();
JFrame calender = new Kalender();
observable.addObserver((Observer) calender);
initComponents();
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)
{
observable.changeData(jTextField1.getText());
}
public static void main(String args[])
{
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Login().setVisible(true);
}
});
}
}

Related

JSliders only sliding halfway

I have a number JSliders in my application and I'm wondering as to why they only slide to half way.
public class test1 extends javax.swing.JFrame {
public test1() {
initComponents();
jSlider1.setExtent(255);
jSlider1.setValue(-255);
}
#SuppressWarnings("unchecked")
private void initComponents() {
jSlider1 = new javax.swing.JSlider();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new test().setVisible(true);
}
});
}
private javax.swing.JSlider jSlider1;
}
Using setExtent or setMaximum would seem to work the same but setExtent makes it so that the slider only slides half way. The proper code looks like this:
public class test1 extends javax.swing.JFrame {
public test1() {
initComponents();
jSlider1.setMaximum(255);
jSlider1.setValue(-255);
}
#SuppressWarnings("unchecked")
private void initComponents() {
jSlider1 = new javax.swing.JSlider();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new test().setVisible(true);
}
});
}
private javax.swing.JSlider jSlider1;
}
You should set jslider1.setMinimum(-255) and jslider1.setMaximum(255) if your intention is to create range from -255 to 255.
You can also implement ChangeListener interface and use addChangeListener to add the listener to the slider. You can do something in the method stateChanged(ChangeEvent e) e.g. updating the RGB color.

How can I effect to another thread? (for example: to setSelect the checkbox)

I created two "jFrame form" with netbeans. I can open the both same time. This codes run but no effect. I try to setSelect a checkbox in form2 with a button in form1. Somehow, I can't effect another thread. Could you please fix it for me. Thanks. (sorry my bad English, I am learning English, too)
This is form1.java (I removed some automatic codes)
package test;
import javax.swing.SwingUtilities;
public class form1 extends javax.swing.JFrame {
public form1() {
initComponents();
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
new form2().setVisible(true);
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
final form2 click = new form2();
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
click.jCheckBox1.setSelected(true);
}
}
);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new form1().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
// End of variables declaration
}
This is form2.java (I removed some automatic codes)
package test;
public class form2 extends javax.swing.JFrame {
public form2() {
initComponents();
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new form2().setVisible(true);
}
});
}
// Variables declaration - do not modify
public javax.swing.JCheckBox jCheckBox1;
// End of variables declaration
}
In your jButton2ActionPerformed method, you're creating a new JFrame which is never shown. You're not manipulating the JFrame you displayed in jButton1ActionPerformed.
Try this:
package test;
import javax.swing.SwingUtilities;
public class form1 extends javax.swing.JFrame {
private form2 click = null; // this will hold the second JFrame (the one with the checkbox)
public form1() {
initComponents();
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
if (click == null) { // only create the second JFrame once
click = new form2(); // this stores the second JFrame with the name "click"
click.setVisible(true);
}
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
if (click != null) { // don't do anything if the second JFrame isn't displayed yet
click.jCheckBox1.setSelected(true);
}
}
}
);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new form1().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
// End of variables declaration
}
BTW, it is bad form and very confusing for class names to start with a lower case letter. Rename form1 to Form1 and form2 to Form2.

spinner image on JFrame while UI are creating

I have an application that after successfull login (on a JFrame), starts to create the main frame (class MainUI that extends from JFrame). That MainUI class contains a JTabbedPane (which each tab is a class that extends from JPanel) and, on setVisible method, creates and shows each tab.
I want to add on the login form, after successfull login, a Spinner image to indicate that the MainUI is being created.
After display the Spinner image, I invoke the creation of the MainUI and call the setVisible method on EventQueue.invokeLater(); but the Spinner image is not updated. If I use new Thread(runner).start(); is updated, but I get a lot of Component creation must be done on Event Dispatch Thread
Some code of Login.java:
buttonLogin.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
login();
}
});
private void login()
{
//check DB and permissions
//if all is ok
lMsj.setIcon(spinner);
new Thread(new Runnable() {
public void run() {
showMainUI(usr);
}
}).start();
}
private void showMainUI(final Usuario usr)
{
Runnable runner = new Runnable() {
public void run() {
final MainUI mui = new MainUI();
mui.setVisible(true);
dispose();
}
};
EventQueue.invokeLater(runner);
}
and some code of MainUI.java
public MainUI()
{
SwingUtilities.invokeLater(new Runnable() {
#Override public void run() {
setMinimumSize(new Dimension(1280, 960));
createComponents();
}
});
}
private void initComponents()
{
//..
// menuItem = new ...
// ...
}
#Override
public void setVisible(boolean value)
{
//..
if (Security.get().isAllowed("tab1")){
addTab1();
}
//..
}
private void addTab1(){
//..
getTabbedPane().addTab("Tab1", new Tab1());
//..
}
How I can fix this, so that the image is updated and the user interface is created in the "background"?

How to update JList from another Thread?

public class ListExample {
public static void main(String[] args) {
final List l=new List();
l.init();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
l.list.updateUI();
System.out.println("Asim");
}
});
}
}
public class List extends JFrame{
public DefaultListModel DLM=new DefaultListModel();
public JList list=new JList(DLM);
private JPanel jp=new JPanel();
private JScrollPane sp=new JScrollPane(list);
public void init(){
jp.add(sp);
super.add(jp);
super.setVisible(true);
super.setLayout(new FlowLayout());
super.setSize(400,500);
UL p=new UL();
p.UL_1();
}
public void Update_list(String[] n){
list.setListData(n);
list.updateUI();
}
}
public class UL extends List{
public void UL_1(){
t.start();
}
Thread t=new Thread(new Runnable() {
#Override
public void run() {
//To change body of implemented methods use File | Settings | File Templates.
String[] n={"Asim", "saif","Khan"};
List l=new List();
l.list.setListData(n);
list.updateUI();
}
});
}
Swing is a single threaded framework, this means that your are expected to only modify the UI elements from within the context of the Event Dispatching Thread. Equally, any long run task or other blocking process will prevent the EDT from processing new events.
While there are a number of ways you might achieve this, probably the simplest would be to use a SwingWorker
For example...
Populate JList with threads
Take a look at Concurrency in Swing for more details
You'd better not to write your java code in that bad-style.
Don not make xxxList extends JFrame ,which will cause misunderstanding.
To use a thread update a list,may be you can start a new thread,like follwing:
Before: not encouraged to use another non EDT thread,incur error.
import java.awt.FlowLayout;
import javax.swing.*;
/*
* This code is bad dealing with Swing component update
*
* Update a Swing component from A Non-EDT thread is not encouraged
* may incur error like:
*
* Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
*/
public class ListExampleBad {
public static void main(String[] args) {
final ListFrame listFrame=new ListFrame();
listFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
//use a thread to update list data
new Thread(new UpdateList(listFrame)).start();
System.out.println("Asim");
}
});
}
}
//list fram with JList
class ListFrame extends JFrame{
public ListFrame(){
jp.add(sp);
super.add(jp);
super.setVisible(true);
super.setLayout(new FlowLayout());
super.setSize(400,500);
}
public synchronized void updateList(String[] n){
list.setListData(n);
list.updateUI();
}
private static final long serialVersionUID = 1L;
private DefaultListModel<String> DLM=new DefaultListModel<String>();
private JList<String> list=new JList<String>(DLM);
private JPanel jp=new JPanel();
private JScrollPane sp=new JScrollPane(list);
}
//runnable dealing with data update
class UpdateList implements Runnable {
public UpdateList(ListFrame listFrame) {
this.ListFrame = listFrame;
}
#Override
public void run() {
// TODO Auto-generated method stub
if(SwingUtilities.isEventDispatchThread()) {
System.out.println("updating list from Event Dispatch Thread");
}else {
System.out.println("updating list NOT from Event Dispatch Thread");
}
String[] n={"Asim", "saif","Khan"};
ListFrame.updateList(n);
}
private ListFrame ListFrame;
}
Thank you who make comments, I update the code:
《core java》 guides us tow principle:
1)don't do a time-consuming job in EDT thread,using a SwingWorker.
2)Except from EDT,don not operate Swing componnet in other thread.
Besides,you can use SwingUtilities.isEventDispatchThread() to check if the job is doing in a EDT thread.
one way: use SwingUtilities.invokeLater
public class ListExampleBetter {
public static void main(String[] args) {
final ListFrameBad listFrame=new ListFrameBad();
listFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//use SwingUtilities.invokeLater,it's ok
SwingUtilities.invokeLater(new UpdateList(listFrame));
}
}
another way:using SwingWoker
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.*;
/**
* This example illustrate updating JList from thread
*/
public class ListExample {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ListFrame listFrame = new ListFrame();
listFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
listFrame.setLocationRelativeTo(null);
listFrame.setVisible(true);
}
});
}
}
//frame with JList
class ListFrame extends JFrame{
public ListFrame(){
super("Update JList Demo");
//initalize data field
dataToUpdate =new String[]{"Asim", "saif","Khan"};
DefaultListModel<String> DLM =new DefaultListModel<String>();
DLM.addElement("wait for update...");;
list =new JList<String>(DLM);
//build gui
JPanel btnPanel = new JPanel();
JButton btnUpdate = new JButton("Update");
btnPanel.add(btnUpdate);
JScrollPane sp=new JScrollPane(list);
this.add(btnPanel,BorderLayout.NORTH);
this.add(sp,BorderLayout.CENTER);
this.setSize(DEFAULT_WIDTH,DEFAULT_HEIGHT);
//deal with action
btnUpdate.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
ListUpdater updater = new ListUpdater();
updater.execute();
}
});
}
public synchronized void updateList(String[] n){
list.setListData(n);
list.updateUI();
}
//using Swingworker to update list
private class ListUpdater extends SwingWorker<Void,String>{
#Override
public Void doInBackground() {
for(String str :dataToUpdate ) {
publish(str);
}
return null;
}
#Override
public void process (List<String> datas) {
for(String str : datas) {
model.addElement(str);
}
}
#Override
public void done() {
if(SwingUtilities.isEventDispatchThread()) {
System.out.println("updating list from Event Dispatch Thread");
}else {
System.out.println("updating list NOT from Event Dispatch Thread");
}
list.setModel(model);
}
private DefaultListModel<String> model =new DefaultListModel<String>();
}
public String[] getDataToUpdate() {
return dataToUpdate;
}
public void setDataToUpdate(String[] dataToUpdate) {
this.dataToUpdate = dataToUpdate;
}
private static final long serialVersionUID = 1L;
private final int DEFAULT_WIDTH = 300,DEFAULT_HEIGHT = 300;
private JList<String> list ;
private String[] dataToUpdate ;
}

How to see communicate between 2 runnable with progression

I have 2 classes .java
The main :
public class Controller extends javax.swing.JFrame
{
public static void updateProgressBar(int i) {
jProgressBar1.setValue(i);
jProgressBar1.repaint();
}
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
Controller app = new Controller();
app.setVisible(true);
app.setResizable(false);
}
});
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
ChildModel model = new ChildModel();
Thread t1 = new Thread(model);
t1.start();
}
private javax.swing.JProgressBar jProgressBar1; //Initialized with Netbeans builder
}
My ChildModel (ChildModel.java) computes some code (that takes around 10-20 sec) and I want to show the progress on the father class (Controller.java).
Here is my ChildModel :
public class ChildModel implements Runnable
{
public ChildModel(){ /* Something */ }
public void complexMath()
{
//Lots of logic here
Controller.updateProgression(purcent);
}
#Override
public void run() {
complexMath();
}
}
The problem is obviously my static void updateProgressBar that cannot modify a non-static variable. How can I accomplish this ?
The jProgressBar1 variable is an instance variable, so you can't access it from a static method. And the method shouldn't be static: you want to update the progress in the controller, and not in all the Controller instances.
Pass a reference to the controller to the ChildModel, and use this reference from the ChildModel in order to update the progress bar. Also remember that all Swing interactions must be done in the EDT, and not in a background thread. SO the code should look like this:
public class Controller extends javax.swing.JFrame
{
public void updateProgressBar(int i) {
jProgressBar1.setValue(i);
// no need for repaint. The progress bar knows it must be repainted
// when its value changes
}
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
Controller app = new Controller();
app.setVisible(true);
app.setResizable(false);
}
});
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
ChildModel model = new ChildModel(this);
Thread t1 = new Thread(model);
t1.start();
}
private javax.swing.JProgressBar jProgressBar1; //Initialized with Netbeans builder
}
public class ChildModel implements Runnable
{
private Controller controller;
public ChildModel(Controller controller){
this.controller = controller;
}
public void complexMath()
{
//Lots of logic here
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
controller.updateProgression(percent);
}
});
}
#Override
public void run() {
complexMath();
}
}
Swing has its own concurrency mechanisms to deal with updating components. Here you could use
a Swing Timer and update the JProgressBar. Rather than have ChildModel implement Runnable, you could use a Timer as a class member variable and pass in your instance jProgressBar1, enabling you to call setValue when required.

Categories