Currently i am working on DEVSJAVA models and trying to make a GUI for those models.
In the below code i have written a displayphase class.In this class whenever a new input arrives it goes into the delext function and then reads the value of the varaible "result" and call the showstate function and then it should paint the result on the JFrame and again when another input arrives it should repaint on the JFrame.
But in the code what i have written makes all the panels print on the JFrame rather than repainting it. I know the error is in adding new panel everytime it goes into the showstate function. But i am unable to make it work.Could please help me out from this error.
package assignment2;
import java.awt.*;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import simView.*;
import genDevs.modeling.*;
import genDevs.simulation.*;
import GenCol.*;
import simView.*;
public class displayphase extends ViewableAtomic{//ViewableAtomic is used instead
//of atomic due to its
//graphics capability
protected entity job;
protected double cul,cll,hul,hll,temp,varout,output,a,b,c,d,g;
protected double processing_time,temperature,temp1,temp2;
protected boolean acStatus,heaterStatus;
protected String result;
**JFrame f=new JFrame();**
public displayphase(){
this("displayphase"
);
}
public displayphase(String name){
super(name);
addInport("in");
addOutport("out");
addInport("in1");
addOutport("out1");
addOutport("out2");
addOutport("out3");
addRealTestInput("in1",71);
addRealTestInput("in",75);
addTestInput("in",new job("job","coolair",72.5),1);
addTestInput("in",new job("job",true,false,60),0);
addRealTestInput("in",3,1);
// processing_time = Processing_time;
}
public void initialize(){
phase = "passive";
sigma = INFINITY;
a=0;b=0;c=0;d=0;g=0;
job = new entity("job");
super.initialize();
}
public void deltext(double e,message x)
{
Continue(e);
if (phaseIs("passive"))
for (int i=0; i< x.getLength();i++)
if (somethingOnPort(x,"in"))
{ job dummy;
entity ent = x.getValOnPort("in",i);
// doubleEnt tem = (doubleEnt) job;
dummy = (job) ent;
temp= dummy.getthetemperature();
result = dummy.getthestate();
heaterStatus = dummy.isHeaterStatus();
System.out.println("The phase in ac"+result);
temperature = temp;
holdIn("busy",processing_time);
}
if (phaseIs("passive"))
for (int i=0; i< x.getLength();i++)
if (somethingOnPort(x,"in1"))
{ job dummy;
entity ent = x.getValOnPort("in1",i);
// doubleEnt tem = (doubleEnt) job;
dummy = (job) ent;
temp= dummy.getthetemperature();
result = dummy.getthestate();
System.out.println("The phase in heater"+result);
heaterStatus = dummy.isHeaterStatus();
temperature=temp;
holdIn("busy",processing_time);
}
**showstate()**;
}
public void deltint( )
{
passivate();
}
public void deltcon(double e,message x)
{
/*deltint();
deltext(20,x);
*/}
public message out( )
{
return outputNameOnPort(result,"out");
}
**public void showstate(){
f.add(new MyPanel());
f.repaint();
f.pack();
f.setVisible(true);
}
class MyPanel extends JPanel {
public MyPanel() {
setBorder(BorderFactory.createLineBorder(Color.black));
}
public Dimension getPreferredSize() {
return new Dimension(250,200);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
String ac,ab;
if(result == "aboveHT" || result=="coolAir")
ac = "cooler on";
else
ac = "cooler off";
/* else if(result == "belowHT" || result == "passive" || result=="belowH")
ac = "cooler off";*/
if(result == "belowHt" )
ab = "Heater on";
else
ab="Heater off";
//String ac=String.valueOf(timesacon());
// JFrame f=new JFrame();
JLabel l=new JLabel("THE STATUS OF AC IS ",JLabel.CENTER);
JLabel p=new JLabel("THE STATUS OF HEATER IS",JLabel.CENTER);
/* p.setVerticalTextPosition(JLabel.BOTTOM);
p.setHorizontalTextPosition(JLabel.CENTER);*/
JTextField t=new JTextField("");
t.setSize(80, 40);
t.setText(ac);
Point p1=new Point(100, 100);
t.setLocation(100,100);
l.setLocation(80, 80);
JTextField v=new JTextField("");
v.setSize(80,40);
v.setText(ab);
Point p2=new Point(100,200);
v.setLocation(p2);
p.setLocation(80, 180);
this.add(l);
this.add(p);
this.add(t);
this.add(v);
this.setSize(500, 300);
// f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// f.pack();
this.setVisible(true);
}
}
}**
Do not modify that state of any component from within any paintXxx method. This will trigger a cascade of repaint events, which will continue to be called until you CPU is running hot and you program is unresponsive...
The paintXxx methods are used to provide the ability to perform custom painting of a component, not modify its state.
Instead, construct the basic UI in the constructor and provide some means by which the state of the fields can be changed, for example, via a updateState method...
import java.awt.Color;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
class MyPanel extends JPanel {
private JTextField t;
private JTextField v;
public MyPanel() {
setBorder(BorderFactory.createLineBorder(Color.black));
JLabel l = new JLabel("THE STATUS OF AC IS ", JLabel.CENTER);
JLabel p = new JLabel("THE STATUS OF HEATER IS", JLabel.CENTER);
t = new JTextField("");
v = new JTextField("");
this.add(l);
this.add(p);
this.add(t);
this.add(v);
}
public void updateState(String result) {
String ac, ab;
if ("aboveHT".equals(result) || "coolAir".equals(result)) {
ac = "cooler on";
} else {
ac = "cooler off";
}
if ("belowHt".equals(result)) {
ab = "Heater on";
} else {
ab = "Heater off";
}
t.setText(ac);
v.setText(ab);
}
}
String comparison in Java is done via the String#equals method. Using == is simply comparing the object memory reference, which has a very low likelihood of ever being true
Without knowing more, I would create an instance of a JFrame, add MyPanel to it and simply call MyPanel#updateState when you need to change it's state.
Modern UI's are expected to be capable of running on a variety of platforms, even when running the same OS, there are differences in the way that fonts may be rendered, making any statically placed and sized components unusable. Instead you should make use of the layout manager API which has being designed to solve this problem with minimal work on your part.
See Laying out components within a container
Related
I'm creating an speed reader so I'm using a swingx.Timer object to display the words at a given time.I set the time to 1sec for testing. I had the code working before but then after closing eclipse and coming back to it the code doesn't work anymore. The timer does not call the actionlistener thus not performing the action it is supposed to perform. Here is my code. I read other questions talking about timer being a daemon thread and ending with main. However I don't think this is the case in my code but I could be wrong. Can someone help me point out my error?
package reader;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Font;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JTextPane;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JMenu;
import java.awt.event.*;
import java.io.IOException;
import java.sql.Time;
import javax.swing.Timer;
public class ReaderPad extends JPanel{
public JButton startBtn, stopBtn, resetBtn;
public JList speedMenu;
public JMenuBar topMenu;
public JTextPane textPad;
public JScrollPane scroll;
public Timer timer;//to control the speed of the reader
public int speed; //the speed set for the reader, i.e. 100 words per minute
public JLabel speedLabel;
public JTextField speedText;
int wordLength; //size of text
String[] lines; //a line of text composed of 10 words from the text entered
int wpm;
int i;//index of word set being used
public ReaderPad(){
this.setLayout(new BorderLayout());
i = 0;
speedLabel = new JLabel("words per minute");
speedText = new JTextField();
speedText.setColumns(3);
startBtn = new JButton("Start");
stopBtn = new JButton("Stop");
resetBtn = new JButton("Reset");
textPad = new JTextPane();
topMenu = new JMenuBar();
textPad.setEditable(true);
textPad.setFont(new Font("Serif", Font.PLAIN,25));
textPad.setText("welcome to speed reader. Use CTRL + c to paste your text\n"
+ "Press start to begin");
scroll = new JScrollPane(textPad);
//create top menu bar
topMenu.add(startBtn);
topMenu.add(stopBtn);
topMenu.add(resetBtn);
topMenu.add(speedLabel);
topMenu.add(speedText);
//topMenu.add(speedMenu);
this.add(topMenu, BorderLayout.NORTH);
this.add(scroll, BorderLayout.CENTER);
//set listeners for buttons
Actions listener = new Actions();
startBtn.addActionListener(listener);
stopBtn.addActionListener(listener);
resetBtn.addActionListener(listener);
}//end of constructor
public void setFontSize(String size){
Font font = textPad.getFont();
String s = font.getName();
textPad.setFont(new Font(s, Font.PLAIN, Integer.valueOf(size)));
}
public void setFontColor(String color){
}
//sets background color
public void setBackgroud(String color){
}
public void setSpeed(String speed){
//speed = speed.replace("X", "");//remove the times symbol
if(speed.isEmpty())//set default
this.speed = 100;
else
this.speed = Integer.valueOf(speed);
}
public int getSpeed(){
return this.speed;
}
public void startReader(){//words per minute
int speed = getSpeed();//wpm selected by the user
System.out.println("speed: " + speed);
String text = textPad.getText();
// System.out.println(text);
lines = text.split(" ");
wordLength = lines.length;//get the number of words in the text
System.out.println("length: "+ wordLength);
//System.out.println(wordLength.length);
if(text.isEmpty()){
textPad.setText("You didn't enter any text in the text area.\n"
+"Please enter some text to begin.");
}
else{//set timer
//calculate speed first: time = (speed chosen * number of workds in text) = (sec/words)*wordsize
//wpm = (1/speed)*wordLength*60*1000; //multiply by 60 secons
wpm = 1000;
System.out.println("wpm: "+ wpm);
TimerReader counter = new TimerReader();
timer = new Timer(1000, counter);
timer.start();
System.out.println(timer.isRunning());
}
}
public void stopReader(){
}
//listener class
public class Actions implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
String source = e.getActionCommand();//read the button asking for the request
if(source.equals("Reset")){
textPad.setText("");
if(timer.isRunning())
timer.stop();
}
else if(source.equals("Start")){
//first read the speed selected and set the speed
setSpeed(speedText.getText());
startReader();
}
else if (source.equals("Stop"))
i = 0;
timer.stop();
}
}
public class TimerReader implements ActionListener{
#Override
public void actionPerformed(ActionEvent e){
//once the timer is called the textpad starts displaying the words
String s = lines[i];
i++;
textPad.setText(s);
System.out.println(i);
System.out.println(e.getActionCommand());
System.out.print(textPad.getText());
}
}//end of inner class
}//end of ReaderPad class
Remove timer.stop() from the end of Actions actionPerformed method...
public class Actions implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
String source = e.getActionCommand();//read the button asking for the request
if (source.equals("Reset")) {
textPad.setText("");
if (timer.isRunning()) {
timer.stop();
}
} else if (source.equals("Start")) {
//first read the speed selected and set the speed
setSpeed(speedText.getText());
startReader();
} else if (source.equals("Stop")) {
i = 0;
}
// This is stopping the timer AFTER it was already started
//timer.stop();
}
}
I'm trying to move a JButton to the location of another one but the button I want to move moves to a wrong point. My idea is that this happens because I use multiple JPanels. I tried: getLocationOnScreen, getBounds and getLocation, but none of them worked, how to solve it? When an user selects a card on the table or from a player by clicking this card the the target is set, the sender is set by clicking a card from the top panel. playerCardSpotTargetand playerCardSpotSender are both of type Card. When I try to move the for example eight of diamonds this card moves to a point behind the eight and nine of clubs.
Code:
This events belong to the blue cards on the table and the cards for the players(I have to change the name of the event, I know).
private void PlayerOneMouseClicked(java.awt.event.MouseEvent evt){
playerCardSpotTarget=(Card)evt.getSource();
if(playerCardSpotTarget.isBorderPainted()){
playerCardSpotTarget.setBorderPainted(false);
}
else{
playerCardSpotTarget.setBorderPainted(true);
}
}
This event belongs to the cards in the top panel.
private void MouseClicked(java.awt.event.MouseEvent evt) {
playerCardSpotSender=(Card)evt.getSource();
System.out.println(playerCardSpotSender.suit+" "+playerCardSpotSender.kind);
if (playerCardSpotTarget != null && playerCardSpotTarget.isBorderPainted()) {
playerCardSpotSender.setLocation(playerCardSpotTarget.getLocation());
System.out.println(playerCardSpotTarget.getLocationOnScreen());
System.out.println(playerCardSpotSender.getLocationOnScreen());
}
}
Layout for the center panel in the JFrame (BorderLayout.CENTER)
JPanel centerPanelNorth;
JPanel centerPanelCenter;
JPanel centerPanelEast;
JPanel centerPanelSouth;
JPanel centerPanelWest;
JLabel tablePicture;
JPanel centerPanel;
centerPanel=new JPanel(new BorderLayout());
tablePicture = new JLabel(new ImageIcon(this.getClass().getResource(Constants.POKERTABLE_ICON)));
centerPanelNorth=new JPanel();
centerPanelEast=new JPanel();
centerPanelSouth=new JPanel();
centerPanelWest=new JPanel();
centerPanelCenter=new JPanel();
centerPanel.add(centerPanelCenter,BorderLayout.CENTER);
centerPanelCenter.add(tablePicture);
//add
tablePicture.add(boardCard1);
tablePicture.add(boardCard2);
tablePicture.add(boardCard3);
tablePicture.setLayout(new GridBagLayout());
//PLAYER NORTH
centerPanel.add(centerPanelNorth,BorderLayout.NORTH);
centerPanelNorth.add(playerOneCardOne);
centerPanelNorth.add(playerOneCardTwo);
//PLAYER EAST
centerPanel.add(centerPanelEast,BorderLayout.EAST);
centerPanelEast.setLayout(new BoxLayout(centerPanelEast,BoxLayout.X_AXIS));
centerPanelEast.add(playerTwoCardOne);
centerPanelEast.add(playerTwoCardTwo);
//PLAYER SOUTH
centerPanel.add(centerPanelSouth,BorderLayout.SOUTH);
centerPanelSouth.add(playerThreeCardOne);
centerPanelSouth.add(playerThreeCardTwo);
//PLAYER WEST
centerPanel.add(centerPanelWest,BorderLayout.WEST);
centerPanelWest.setLayout(new BoxLayout(centerPanelWest,BoxLayout.X_AXIS));
centerPanelWest.add(playerFourCardOne);
centerPanelWest.add(playerFourCardTwo);
Card.java
public class Card extends JButton{
int suit;
int kind;
boolean known;
String iconPath;
Integer boardPosition;
}
Animating the button movement isn't actually the hardest problem, the hardest problem is trying to move the data about in away in which you can manage it and how to connect the source component with the target...
To start with, you need a means by which you can move a component across container boundaries. While there are probably a few ways to do this, the simplest is to probably use the glass pane of the frame
public class AnimationPane extends JPanel {
public AnimationPane() {
setOpaque(false);
setLayout(null);
}
}
This is nothing special, it's just a JPanel which is transparent and has no layout manager, normally, not recommended, but in the case, we're going to take control..
Now, we need some way to animate the movement...
public enum Animator {
INSTANCE;
private List<IAnimatable> animatables;
private Timer timer;
private Animator() {
animatables = new ArrayList<>(25);
timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
IAnimatable[] anins = animatables.toArray(new IAnimatable[animatables.size()]);
for (IAnimatable animatable : anins) {
animatable.update();
}
}
});
timer.start();
}
public void addAnimatable(IAnimatable animatable) {
animatables.add(animatable);
}
public void removeAnimatable(IAnimatable animatable) {
animatables.remove(animatable);
}
}
public interface IAnimatable {
public void update();
}
public interface IMoveAnimatable extends IAnimatable{
public JComponent getSourceComponent();
public IImportable getImportable();
}
So the Animator is the core "engine", it's basically a Swing Timer which simply calls update on any IAnimatables it might be managing. The intention with this approach is you can have a number of animations running, but it won't degrade the system (greatly) as you only have a single update/timer point.
Now, normally I'd just use something like the Timing Framework or the Trident Framework or even the Universal Tween Engine
The IAnimatable interfaces just define the basic contracts that provide functionality for the animation.
We need to define some kind of contract the defines objects which can take part in the animation process and receive information, or the "target"
public interface IImportable {
public JComponent getView();
public void importValue(String value);
}
public abstract class AbstractImportable extends JPanel implements IImportable {
#Override
public JComponent getView() {
return this;
}
}
Now it occurs to me that we could tap into the pre-existing Transferable API, which would allow you to also implement drag-n-drop (and even copy/cut and paste), this would be used to define a lookup mechanism where you match a given data type with potential targets based on the DataFlavor ... but I'll leave you to investigate how that might work...
The core mechanism basically removes the source component from it's current container, adds it to the AnimationPane, moves the source component across the AnimationPane and then imports the data into the target...
The problem is, you need to translate the location of component from it's current context to the AnimationPane.
A components location is relative to it's parents context. It's relatively easy to do with SwingUtilities.convertPoint(Component, Point, Component)
We calculate the origin point of the source component and the target point, relative to the AnimationPane. We then, on each call to update, calculate the progress of the animation. Instead of using a "delta" movement, we calculate the different between the time we started and a predefined duration (1 second in this case), this generally produces a more flexible animation
public class DefaultAnimatable implements IMoveAnimatable {
public static final double PLAY_TIME = 1000d;
private Long startTime;
private JComponent sourceComponent;
private IImportable importable;
private JComponent animationSurface;
private Point originPoint, destinationPoint;
private String value;
public DefaultAnimatable(JComponent animationSurface, JComponent sourceComponent, IImportable importable, String value) {
this.sourceComponent = sourceComponent;
this.importable = importable;
this.animationSurface = animationSurface;
this.value = value;
}
public String getValue() {
return value;
}
public JComponent getAnimationSurface() {
return animationSurface;
}
#Override
public JComponent getSourceComponent() {
return sourceComponent;
}
#Override
public IImportable getImportable() {
return importable;
}
#Override
public void update() {
if (startTime == null) {
System.out.println("Start");
IImportable importable = getImportable();
JComponent target = importable.getView();
originPoint = SwingUtilities.convertPoint(getSourceComponent().getParent(), getSourceComponent().getLocation(), getAnimationSurface());
destinationPoint = SwingUtilities.convertPoint(target.getParent(), target.getLocation(), getAnimationSurface());
destinationPoint.x = destinationPoint.x + ((target.getWidth() - getSourceComponent().getWidth()) / 2);
destinationPoint.y = destinationPoint.y + ((target.getHeight() - getSourceComponent().getHeight()) / 2);
Container parent = getSourceComponent().getParent();
getAnimationSurface().add(getSourceComponent());
getSourceComponent().setLocation(originPoint);
parent.invalidate();
parent.validate();
parent.repaint();
startTime = System.currentTimeMillis();
}
long duration = System.currentTimeMillis() - startTime;
double progress = Math.min(duration / PLAY_TIME, 1d);
Point location = new Point();
location.x = progress(originPoint.x, destinationPoint.x, progress);
location.y = progress(originPoint.y, destinationPoint.y, progress);
getSourceComponent().setLocation(location);
getAnimationSurface().repaint();
if (progress == 1d) {
getAnimationSurface().remove(getSourceComponent());
Animator.INSTANCE.removeAnimatable(this);
animationCompleted();
}
}
public int progress(int startValue, int endValue, double fraction) {
int value = 0;
int distance = endValue - startValue;
value = (int) Math.round((double) distance * fraction);
value += startValue;
return value;
}
protected void animationCompleted() {
getImportable().importValue(getValue());
}
}
Okay, now this produces a linear animation, which is pretty boring, now if you have plenty of time, you could create an easement like this or just use one of the animation frameworks...
Now, we need to put it together...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
public class AnimationTest {
public static void main(String[] args) {
new AnimationTest();
}
public AnimationTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
AnimationPane animationPane = new AnimationPane();
LeftPane leftPane = new LeftPane(animationPane);
RightPane rightPane = new RightPane();
leftPane.setImportabale(rightPane);
rightPane.setImportabale(leftPane);
JFrame frame = new JFrame("Testing");
frame.setLayout(new GridLayout(1, 2));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(leftPane, BorderLayout.WEST);
frame.add(rightPane, BorderLayout.WEST);
frame.setGlassPane(animationPane);
animationPane.setVisible(true);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class RightPane extends AbstractImportable {
private IImportable source;
private JButton imported;
private String importedValue;
public RightPane() {
setLayout(new GridBagLayout());
setBorder(new LineBorder(Color.DARK_GRAY));
}
public void setImportabale(IImportable source) {
this.source = source;
}
#Override
public void importValue(String value) {
if (imported != null) {
// May re-animate the movement back...
remove(imported);
}
importedValue = value;
imported = new JButton(">> " + value + "<<");
add(imported);
revalidate();
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public class LeftPane extends AbstractImportable {
private IImportable importable;
public LeftPane(AnimationPane animationPane) {
setLayout(new GridBagLayout());
JButton btn = new JButton("Lefty");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
DefaultAnimatable animatable = new DefaultAnimatable(animationPane, btn, importable, "Lefty");
Animator.INSTANCE.addAnimatable(animatable);
}
});
add(btn);
setBorder(new LineBorder(Color.DARK_GRAY));
}
public void setImportabale(IImportable target) {
this.importable = target;
}
#Override
public void importValue(String value) {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
Maybe use mousePressed(),when you move the card,you press it until the target.And in the process, you get the information about JButton.getLocation() by the event,and than you need to solve the collision problem between two cards.So it's good!Of course, this is my advice ,you should have better idea!
I had some problems with freezing SWING GUIs when re-rendering a JTable with a custom cell renderer in Java. So I asked the question "Why does a JTable view update block the entire GUI?". The answers pointed to the fact, that a JList without modifying JTable and overwriting doLayout might be a better choice. So I implemented the example with a JList and ran into the same problem: while generating data, everything works fine and the progress bar moves. But when the view is updated, the program freezes and the progress bar stops moving.
Please note, that the sleep statement is there only to let the generation take a longer, more realistic time (reading thousands of data sets via JDBC and create objects out of them takes a lot time). One could remove it and increment the number of generated items. But you can clearly see, that the HTML rendering is quite slow. But I need this colors and the two lines (if not necessarily so many different colors).
So could you please tell me, where my mistake is? I think, that EDT and other work is separated through separate threads and I cannot see any mistke.
Update: I looked around at SO and found this question "https://stackoverflow.com/a/20813122/2429611". There is said:
The more interesting question would be how to avoid that UI blocking, but I don't think that's possible with just Swing, you'll have to implement some lazy loading, or rendering in batches.
This would mean, that I cannot solve my problem. Is this correct?
package example;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.AbstractListModel;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
import javax.swing.SwingUtilities;
public class ListExample extends AbstractListModel {
static List<DemoObject> internalList = new ArrayList<>();
#Override
public int getSize() {
return internalList.size();
}
#Override
public DemoObject getElementAt(int index) {
return internalList.get(index);
}
public void fireContentsChanged() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
fireContentsChanged(this, 0, -1);
}
});
}
static class MyCellRenderer extends JLabel implements ListCellRenderer<ListExample.DemoObject> {
public MyCellRenderer() {
setOpaque(true);
}
#Override
public Component getListCellRendererComponent(JList<? extends ListExample.DemoObject> list,
ListExample.DemoObject value,
int index,
boolean isSelected,
boolean cellHasFocus) {
setText("<html>" + value.toString()
+ "<br/>"
+ "<span bgcolor=\"#ff0000\">Line 2; Color = " + value.c + "</span>");
Color background;
Color foreground;
// check if this cell represents the current DnD drop location
JList.DropLocation dropLocation = list.getDropLocation();
if (dropLocation != null
&& !dropLocation.isInsert()
&& dropLocation.getIndex() == index) {
background = Color.BLUE;
foreground = Color.WHITE;
// check if this cell is selected
} else if (isSelected) {
background = Color.RED;
foreground = Color.WHITE;
// unselected, and not the DnD drop location
} else {
background = value.c; //Color.WHITE;
foreground = Color.BLACK;
};
setBackground(background);
setForeground(foreground);
return this;
}
}
static class DemoObject {
String str;
Color c;
public DemoObject(String str, int color) {
this.str = str;
this.c = new Color(color);
}
#Override
public String toString() {
return str;
}
}
static JPanel overlay;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Example");
frame.setLayout(new BorderLayout(4, 4));
// Add JTable
final ListExample model = new ListExample();
JList list = new JList(model);
list.setCellRenderer(new MyCellRenderer());
frame.add(new JScrollPane(list), BorderLayout.CENTER);
// Add button
Box hBox = Box.createHorizontalBox();
hBox.add(new JButton(new AbstractAction("Load data") {
#Override
public void actionPerformed(ActionEvent e) {
new Thread(new Runnable() {
#Override
public void run() {
overlay.setVisible(true);
internalList.clear();
System.out.println("Generating data ...");
SecureRandom sr = new SecureRandom();
for (int i = 0; i < 10000; i++) {
internalList.add(
new DemoObject(
"String: " + i + " (" + sr.nextFloat() + ")",
sr.nextInt(0xffffff)
)
);
// To create the illusion, that data are
// fetched via JDBC (which takes a little
// while), this sleep statement is embedded
// here. In a real world scenario, this wait
// time is caused by talking to the database
// via network
if (i%10 == 0) {
try {
Thread.sleep(1);
} catch (Exception e) {
}
}
}
System.out.println("Updating view ...");
model.fireContentsChanged();
overlay.setVisible(false);
System.out.println("Finished.");
}
}).start();
}
}));
hBox.add(Box.createHorizontalGlue());
frame.add(hBox, BorderLayout.NORTH);
// Create loading overlay
overlay = new JPanel(new FlowLayout(FlowLayout.CENTER)) {
#Override
protected void paintComponent(Graphics g) {
g.setColor(new Color(0, 0, 0, 125));
g.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(g);
}
};
overlay.setOpaque(false);
overlay.setBackground(new Color(0, 0, 0, 125));
JProgressBar bar = new JProgressBar();
bar.setIndeterminate(true);
overlay.add(bar);
frame.setGlassPane(overlay);
frame.getGlassPane().setVisible(false);
// Create frame
frame.setSize(600, 400);
frame.setVisible(true);
}
});
}
}
there are three problems (recreating, reseting the model, and custom Renderer stoped to works)
JList (JComboBox hasn't) has an issue by removing more than 999 items, you have to set a new model to JList
see important for ComboBoxModel extends AbstractListModel implements MutableComboBoxModel for setElementAt(to hold current selection)
usage of public void fireContentsChanged() { is wrong, don't see reason to use this way, again is about to replace current, reset the model
. e.g. with success atr runtime and by recrusive testing for/if event (fired)
setModel(new DefaultListModel(list.toArray()) {
protected void fireContentsChanged(Object obj, int i, int j) {
if (!isFired)
super.fireContentsChanged(obj, i, j);
}
});
I am making a vocabulary quiz program and when they click an option, a new window is supposed to pop up saying if they got it right or wrong. That works, but what doesn't show is the button in the window when it gives you the option to go back to the quiz, ruining the chance to continue onto the next question, or even worse, answering the current question.
Here is the main quiz code:
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.DataFormatter;
public class SAT extends JFrame implements ActionListener{
private JButton buttonA;
private JButton buttonB;
private JButton buttonC;
private JButton buttonD;
private JPanel panel1;
private JFrame frame1;
private JTextField Text1;
private JLabel label1;
public static final String POOP = "Words3.xls"; //everywhere that there is POOP is the excel sheet
public static String read1(int rowIndex, int colIndex, int a)
{
String value = new String();
HSSFWorkbook wb = null;
try {
wb = new HSSFWorkbook(new FileInputStream(POOP));
} catch (Exception e) {
e.printStackTrace();
}
String sheet2=null;//placeholder
if (a==1){sheet2="SAT";}//one of these for each sheet
if (a==2){sheet2="Test";}
if (a==3){sheet2="vwlvlHU1";}
HSSFSheet sheet = wb.getSheet(sheet2);
HSSFRow row=sheet.getRow(rowIndex-1);
HSSFCell cell=row.getCell(colIndex-1);
DataFormatter formatter = new DataFormatter();
value = formatter.formatCellValue(cell);
return value;
}
private static void saveWorkbook(HSSFWorkbook wb) throws IOException
{
FileOutputStream out = new FileOutputStream(POOP);
wb.write(out);
out.close();
}
public static int RNG1(int a) { //this RNG is used to find the word and random definitions
//RNG code:
int min=1;//1
int max=100;//number of flash cards, highest number, this is a placeholder
if (a==1){max=253;}//we will have one of these statements for each set
if (a==2){max=20;}
if (a==3){max=40;}
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min + 1;//the +1 is so it doesn't choose header, maybe remove
return randomNum;
}
public static int RNG2(int b) {//this RNG will be used to determine which button gets true definition
//RNG code:
int min=1;//1
int max=4;//number of options
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
//FIND THE WORD AND POS
int a=1;//tells methods to look in right set
int rowIndex=RNG1(a);//here is where a random word, pos, and def will be called for
int colIndex=1;//use colIndex=1 to show word
String WORD=read1(rowIndex,colIndex,a);//to pull word
//System.out.println("Word: "+WORD);
int colIndexPOS=2;//POS=part of speech/colIndexPOS=2 for part of speech
String POS=read1(rowIndex,colIndexPOS,a);
//System.out.println("Part of speech: "+POS);
int b=1;//placeholder
int location=RNG2(b);
//if location=1, put it in button 1 and have random definitions for other 3
//if location=2... same for 3 and 4
private String def(){
//TRUE DEFINITION:
int colIndexDEF=3;//DEF= definition/colIndexPOS=3 for definitions
String DEF=read1(rowIndex,colIndexDEF,a);
return DEF;
}
//FAKE DEFINITIONS:
//fake def 1:
private String rdef1(){//THIS BLOCK HAS AN ISSUE. SHOULD NOT BE DIVIDED BY CURLY BRACES BUT IT IS AN ERROR IF THEY ARE NOT THERE. MAYBE MAKE IT A METHOD?
int rowIndex1=0;//null value
int colIndexDEF=3;
String weirdo="WHY";
do{
rowIndex1=RNG1(a);
weirdo=read1(rowIndex1, colIndexPOS, a);
}while(rowIndex1==rowIndex || !weirdo.equals(POS));
String RANDDEF1=read1(rowIndex1, colIndexDEF, a);
return RANDDEF1;
}
//fake def 2:
private String rdef2(){//FIX DOWHILE
int rowIndex2=1;//null value
int colIndexDEF=3;
String POSsave1=null;
//do{
rowIndex2=RNG1(a);
POSsave1=read1(rowIndex2, colIndexPOS, a);
//}while(rowIndex2==rowIndex1 || rowIndex2==rowIndex || !POSsave1.equals(POS));
String RANDDEF2=read1(rowIndex2, colIndexDEF, a);
return RANDDEF2;
}
//fake def 3:
private String rdef3(){//FIX DOWHILE
int rowIndex3=1;//null value
int colIndexDEF=3;
String POSsave2=null;
//do{
rowIndex3=RNG1(a);
POSsave2=read1(rowIndex3, colIndexPOS, a);
//}while(rowIndex3==rowIndex || rowIndex3==rowIndex2 || rowIndex3==rowIndex1 || !POSsave2.equals(POS));
String RANDDEF3=read1(rowIndex3, colIndexDEF, a);
return RANDDEF3;
}
private void createButtonA() {
String definition=null;
if (location==1){
definition=def();
}
if (location==2){
definition=rdef1();
}
if (location==3){
definition=rdef2();
}
if (location==4){
definition=rdef3();
}
buttonA = new JButton(definition);
add(buttonA);
buttonA.setContentAreaFilled(false);
buttonA.addActionListener((ActionListener) this);//this allows an action to be performed when the button is pressed
buttonA.setForeground(Color.blue);
buttonA.setBounds(45,130,295,25);
}
private void createButtonB() {
String definitionB=null;
if (location==1){
definitionB=rdef1();
}
if (location==2){
definitionB=def();
}
if (location==3){
definitionB=rdef3();
}
if (location==4){
definitionB=rdef2();
}
buttonB = new JButton(definitionB);
add(buttonB);
buttonB.setContentAreaFilled(false);
buttonB.addActionListener((ActionListener) this);//this allows an action to be performed when the button is pressed
buttonB.setForeground(Color.blue);
buttonB.setBounds(45,95,295,25);
}
private void createButtonC() {
String definitionC=null;
if (location==1){
definitionC=rdef2();
}
if (location==2){
definitionC=rdef3();
}
if (location==3){
definitionC=def();
}
if (location==4){
definitionC=rdef1();
}
buttonC = new JButton(definitionC);
add(buttonC);
buttonC.setContentAreaFilled(false);
buttonC.addActionListener((ActionListener) this);//this allows an action to be performed when the button is pressed
buttonC.setForeground(Color.blue);
buttonC.setBounds(45,60,295,25);
}
private void createButtonD() {
String definitionD=null;
if (location==1){
definitionD=rdef3();
}
if (location==2){
definitionD=rdef2();
}
if (location==3){
definitionD=rdef1();
}
if (location==4){
definitionD=def();
}
buttonD = new JButton(definitionD);
add(buttonD);
buttonD.setContentAreaFilled(false);
buttonD.addActionListener((ActionListener) this);//this allows an action to be performed when the button is pressed
buttonD.setForeground(Color.blue);
buttonD.setBounds(45,25,295,25);
}
public static void main(String[] args) {
SAT frameTable = new SAT();
//frameTable.SAT(); //Creating Frame
frameTable.createButtonA(); //Creating Button 1
frameTable.createButtonB(); //Creating Button 2
frameTable.createButtonC();//Creating button 3
frameTable.createButtonD();//Creating button 3
}
public SAT() {//problem
Container window = getContentPane();
window.setLayout(new FlowLayout() ); //using the FlowLayout manager
setSize(400,250); //setting the size of the initial box
setVisible(true); //allows for manual size changing of the box
setTitle("FlaQuiZ"); //Title for the GUI
window.setBackground(Color.white);
setLocation(500,280);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Allows us to actually exit when we click the "X"
panel1 = new JPanel(new GridLayout());
add(new JLabel("Choose the option that best fits this word: "+WORD));
//add(new JLabel(""));
}
public void actionPerformed(ActionEvent i) {
if ( location==1 && i.getSource() == buttonA || location==2 && i.getSource()==buttonB || location==3 && i.getSource()==buttonC || location==4 && i.getSource()==buttonD) {
GRATS congrats =new GRATS();
congrats.setVisible(true);
dispose();
}
else{
NO bad =new NO();
bad.setVisible(true);
dispose();
}
}
}
And then here would be the code if they got it wrong, where the button should appear to give the option to go back:
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class NO extends JFrame implements ActionListener{
private JButton NOB;
private JPanel panel3;
public NO() {
Container window = getContentPane();
window.setLayout(new FlowLayout() ); //using the FlowLayout manager
setSize(275,160); //setting the size of the initial box
setVisible(true); //allows for manual size changing of the box
setTitle("Flaquiz"); //Title for the GUI
window.setBackground(Color.white);
setLocation(500,280);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Allows us to actually exit when we click the "X"
JPanel panel3 = new JPanel(new GridLayout());
add(new JLabel("Uh oh, you got it wrong!"));
//add(new JLabel(""));
}
public static void main(String[] args) {
NO bad = new NO();
//frameTable.SAT(); //Creating Frame
bad.createbuttonNOB(); //Creating Button 1
}
private void createbuttonNOB() {
NOB = new JButton("Go Back");
add(NOB);
NOB.setContentAreaFilled(false);
NOB.addActionListener((ActionListener) this);//this allows an action to be performed when the button is pressed
NOB.setForeground(Color.blue);
NOB.setBounds(45,45,45,45);
}
public void actionPerformed(ActionEvent i) {
if (i.getSource() == NOB ) {
SAT goback =new SAT();
goback.setVisible(true);
dispose();
}
}
}
I may be missing something, but it seems you add the button directly to the JFrame even though you have a JPanel occupying the whole frame. Why not add the button to the JPanel?
Side Note: In the NO constructor, SetVisible doesn't determine whether or not you can manually change size. That's controlled by things like SetMaximumSize, SetMinimumSize, and SetResizable.
I have 3 clasess : Loader, MyDialog and TEST(with main method). (for code see below)
Everything I want to achieve is create simple dialog with JLabel and JProgressBar, which will notify user about how much time remains to show MyDialog. MyDialog is Jdialog with time consuming operation in constructor (loading data from database etc.).
In code below is model situation. When "MyDialog" is created by main (constant BY_USER is false), everything working exactly i want to. But when i make dialog with button , and instance of MyDialog is created after button press (constant BY_USER is true), Loader is blank white form. It looks like is not completed.
Loader is extending Thread, so i suppose that problem will be in threading (event dispatch thread)? I dont know, what is wrong and how fix it. Please help.
Thanks and sorry for my English.
CLASS TEST :
package test;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
public class TEST {
public static final boolean BY_USER = false;
public static void main(String[] args) {
if (BY_USER) {
JFrame mainDialog = new JFrame("Main");
JButton show = new JButton("Show MyDialog");
show.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
MyDialog dialog = new MyDialog();
}
});
mainDialog.add(show);
mainDialog.setLocationRelativeTo(null);
mainDialog.setMinimumSize(new Dimension(160, 80));
mainDialog.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
mainDialog.setVisible(true);
} else {
MyDialog dialog = new MyDialog();
}
}
}
CLASS MyDialog :
package test;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
public class MyDialog extends JFrame{
public MyDialog() {
super();
// making loader with title, first message and count of steps of operation
Loader loader = new Loader("Loader", "First showed message", 100);
loader.ShowLoader();
// time-consuming operation (loading data from database etc.).
// for clarity replaced with for statement
int j=0;
for(int i=0; i<Integer.MAX_VALUE; i++)
{
j++;
if(j==Integer.MAX_VALUE/100){
// updating loader message and progress bar value
loader.NewAction(Integer.MAX_VALUE - i+"");
j=0;
}
}
// closing loader
loader.DestroyLoader();
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
this.setSize(300, 300);
this.setLocationRelativeTo(null);
this.setVisible(true);
}
}
CLASS Loader:
package test;
import java.awt.BorderLayout;
import java.awt.Dialog;
import java.awt.Dimension;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.SwingConstants;
public class Loader extends Thread{
private JDialog dialog;
private JLabel message = new JLabel("", SwingConstants.CENTER);
private JProgressBar progressBar = new JProgressBar(0, 100);
private String newMessage;
private double percentForStep;
private int remainingSteps;
public Loader(String taskName, String firstMessage, int steps) {
this.remainingSteps = steps-1;
dialog = new JDialog((Dialog) null, taskName);
dialog.setLayout(new BorderLayout(15, 15));
dialog.add(message, BorderLayout.CENTER);
dialog.add(progressBar, BorderLayout.SOUTH);
message.setText(firstMessage);
percentForStep = 100 / steps;
}
public void ShowLoader()
{
dialog.setMinimumSize(new Dimension(400,120));
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
this.start();
}
public void DestroyLoader(){
dialog.dispose();
this.interrupt();
}
public void NewAction(String newMessage){
this.newMessage = newMessage;
this.remainingSteps--;
Lock.changed = true;
}
public int RemainingStepsCount()
{
return remainingSteps;
}
#Override
#SuppressWarnings({"CallToThreadYield", "SleepWhileInLoop"})
public void run() {
do{
synchronized (Lock.class) {
if (Lock.changed) {
Lock.changed = false;
this.message.setText(newMessage);
this.progressBar.setValue((int)(100-(remainingSteps*percentForStep)));
dialog.repaint();
}
dialog.repaint();
}
}while(true);
}
}
class Lock{
static boolean changed = false;
}
Look to SwingWorker and his use; I think it can help you to solve the problem.