How to dispose the old font of a Button in swt java - java

I'm trying to update a button's font at regular intervals, and this is how I implement it.
Font font = buttons.getFont();
FontData[] fontData = font.getFontData();
for(int j = 0; j < fontData.length; ++j) {
fontData.setStyle(SWT.ITALIC | SWT.BOLD);
}
font = new Font(display, fontData);
buttons.setFont(font);
but doing this make the program crashed after some time with the exception
org.eclipse.swt.SWTError: No more handles
at org.eclipse.swt.SWT.error(SWT.java:4387)
at org.eclipse.swt.SWT.error(SWT.java:4276)
at org.eclipse.swt.SWT.error(SWT.java:4247)
at org.eclipse.swt.widgets.Display.error(Display.java:1258)
at org.eclipse.swt.widgets.Display.internal_new_GC(Display.java:2673)
at org.eclipse.swt.graphics.Device.computePoints(Device.java:241)
at org.eclipse.swt.graphics.Font.getFontData(Font.java:188)
My guess is that I've created many font objects without disposing them in time. but I have no idea how to dispose them correctly, can anyone help me with it? if my guess is wrong, pls tell me what's the true reason of the no handle exception?

try using getFont().dispose() and setFont() on button as,
final Font arialFont = new Font(Display.getCurrent(), "Arial", 40,
SWT.NORMAL);
final Font courierFont = new Font(Display.getCurrent(), "Courier New",
8, SWT.NORMAL);
final Button btn = new Button(parent, SWT.NONE);
btn.setText("New Text");
btn.setSize(100, 30);
btn.setFont(arialFont);
Button changeBtn = new Button(parent, SWT.NONE);
changeBtn.setText("Change Font");
changeBtn.setSize(100, 30);
changeBtn.addSelectionListener(new SelectionListener() {
#Override
public void widgetSelected(SelectionEvent arg0) {
count = count + 1;
if (count % 2 == 0) {
btn.getFont().dispose();
btn.setFont(arialFont);
} else {
btn.getFont().dispose();
btn.setFont(courierFont);
}
}
#Override
public void widgetDefaultSelected(SelectionEvent arg0) {
// TODO Auto-generated method stub
}
});

Related

How can I generalize these repetitive blocks of code?

Code with near-identical blocks like this makes me cringe. Plus it adds up to where you have a thousand lines of code where half that would suffice. Surely there is a way to make a loop to make it all happen and not have code that looks so unsophisticated and brainless.
Offhand it seems like to do so would be adding as much code as I seek to reduce: loop to make 5 buttons, array of labels for the buttons, array of backgrounds... maybe more. Even if that turned out to be acceptable, how would I make a loop to handle the listeners? I can't have an array of methods, can I? I guess such a loop it would have to include a switch. Yes? I'd probably do that if I didn't want to seek a better solution. So I'm asking...
What would code look like that would listen to the entire group of buttons and take action based on which one was pressed? To which component would I assign the single listener? And how?
(There's a chance that the answer to that question will make me cringe even more than the repetitive nature of the code, if I realize that I already know how to do so and needn't have even asked in the first place, but I'm asking anyway. I'm at one of those I've-had-it-for-today points where the brain just wants out.)
private void makeScoremasterBonuses(){
pnlBonuses = new JPanel(new GridLayout(1, 6));
pnlBonuses.setSize(6,1);
JButton t1 = (new JButton("3W"));
t1.setToolTipText("This is a triple-word cell.");
t1.setBackground(TRIPLE_WORD);
t1.setHorizontalAlignment(JButton.CENTER);
t1.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
Highlighter.shadeSymmetric(currentCell,TRIPLE_WORD);
}});
JButton t2 = (new JButton("3L"));
t2.setToolTipText("This is a triple-letter cell");
t2.setBackground(TRIPLE_LETTER);
t2.setHorizontalAlignment(JButton.CENTER);
t2.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
Highlighter.shadeSymmetric(currentCell,TRIPLE_LETTER);
}});
JButton t3 = (new JButton("2W"));
t3.setToolTipText("This is a double-word cell");
t3.setBackground(DOUBLE_WORD);
t3.setHorizontalAlignment(JButton.CENTER);
t3.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
Highlighter.shadeSymmetric(currentCell,DOUBLE_WORD);
}});
JButton t4 = (new JButton("2L"));
t4.setToolTipText("This is a double-letter cell");
t4.setBackground(DOUBLE_LETTER);
t4.setHorizontalAlignment(JButton.CENTER);
t4.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
Highlighter.shadeSymmetric(currentCell,DOUBLE_LETTER);
}});
JButton t5 = (new JButton(""));
t5.setToolTipText("No bonus");
t5.setBackground(WHITE);
t5.setHorizontalAlignment(JButton.CENTER);
t5.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
Highlighter.shadeSymmetric(currentCell,B_NORMAL);
}});
pnlBonuses.add(new JLabel("Legend: "));
pnlBonuses.add(t1);
pnlBonuses.add(t2);
pnlBonuses.add(t3);
pnlBonuses.add(t4);
pnlBonuses.add(t5);
}
I'm not asking anyone to write the code; I wouldn't even want that (but I couldn't ignore it!).
Here's what the code above does:
Generally any time you have repeated functionality like that, you want to extract that code out into a helper method like this:
private JButton makeJButton(String label, String toolTip, Color bgColor, final Color highlight) {
JButton button = new JButton(label);
button.setToolTipText(toolTip);
button.setBackground(bgColor);
button.setHorizontalAlignment(JButton.CENTER);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Highlighter.shadeSymmetric(currentCell, highlight);
}
});
return button;
}
Then your makeScoremasterBonuses() method becomes much simpler:
private void makeScoremasterBonuses() {
pnlBonuses = new JPanel(new GridLayout(1, 6));
pnlBonuses.setSize(6, 1);
pnlBonuses.add(new JLabel("Legend: "));
pnlBonuses.add(makeJButton("3W", "This is a triple-word cell.", TRIPLE_WORD, TRIPLE_WORD));
pnlBonuses.add(makeJButton("3L", "This is a triple-letter cell.", TRIPLE_LETTER, TRIPLE_LETTER));
pnlBonuses.add(makeJButton("2W", "This is a double-word cell.", DOUBLE_WORD, DOUBLE_WORD));
pnlBonuses.add(makeJButton("3L", "This is a double-letter cell.", DOUBLE_LETTER, DOUBLE_LETTER));
pnlBonuses.add(makeJButton("", "No bonus.", WHITE, B_NORMAL));
}
Identify the aspects that vary, collect them, and iterate over the collection.
Something like this (untested):
pnlBonuses = new JPanel(new GridLayout(1, 6));
pnlBonuses.setSize(6,1);
pnlBonuses.add(new JLabel("Legend: "));
// Create class "CellInfo" with constructor and getters for desired properties.
CellInfo cellInfos[] = {
new CellInfo("3W", "This is a triple-word cell.", TRIPLE_WORD),
new CellInfo("3L", "This is a triple-letter cell.", TRIPLE_LETTER),
// ...
};
// Add a button for each item described by the cellInfos.
for (CellInfo cellInfo : cellInfos) {
Button b = new JButton(cellInfo.getLabel());
b.setToolTipText(cellInfo.getToolTipText());
b.setBackground(cellInfo.getBackground());
b.setHorizontalAlignment(JButton.CENTER);
b.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
Highlighter.shadeSymmetric(currentCell, cellInfo.getBackground());
}});
pnlBonuses.add(b);
}
Note that you might need to create some "final" variables for placeholders for use in the inner anonymous class but the idea should work.
An enum could be your friend here. It's almost an array of methods:
static enum Btn {
TripleWord("3W", "This is a triple word cell.", TRIPLE_WORD),
TripleLetter("3L", "This is a triple letter cell.", TRIPLE_LETTER),
DoubleWord("2W", "This is a double word cell.", DOUBLE_WORD),
DoubleLetter("2L", "This is a double letter cell.", DOUBLE_LETTER),
NoBonus("", "No bonus.", WHITE, B_NORMAL);
final String label;
final String tooltip;
final Color color;
final Color shade;
Btn(String label, String tooltip, Color color, Color shade) {
this.label = label;
this.tooltip = tooltip;
this.color = color;
this.shade = shade;
}
Btn(String label, String tooltip, Color color) {
this(label, tooltip, color, color);
}
public JButton asJButton() {
JButton btn = (new JButton(label));
btn.setToolTipText(tooltip);
btn.setBackground(color);
btn.setHorizontalAlignment(JButton.CENTER);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Highlighter.shadeSymmetric(currentCell, shade);
}
});
return btn;
}
}
private void makeScoremasterBonuses() {
int nBtns = Btn.values().length;
JPanel pnlBonuses = new JPanel(new GridLayout(1, nBtns + 1));
pnlBonuses.setSize(nBtns + 1, 1);
pnlBonuses.add(new JLabel("Legend: "));
for (Btn btn : Btn.values()) {
pnlBonuses.add(btn.asJButton());
}
}
(I know I could have edited my previous answer, but this one's so different...)
Thanks to #OldCurmudgeon, I have come up with what I think is pretty good.
Here's "proof" (I may just leave each label and tooltip as is):
public enum Colors {
TRIPLE_WORD (255, 220, 50),
TRIPLE_LETTER (255, 255, 150),
DOUBLE_WORD ( 0, 255, 0),
DOUBLE_LETTER (214, 245, 214),
NOT_A_BONUS (255, 255, 255);
private final int red, green, blue;
Colors(int r, int g, int b){
this.red = r;
this.green = g;
this.blue = b;
}
public java.awt.Color background(Colors c){
return new java.awt.Color(c.red, c.green, c.blue);
}
}
private void makeScoremasterBonuses(){
Colors c;
Colors all [] = Colors.values();
String labels[] = new String[all.length];
String abbrs [] = new String[all.length];
JButton but;
pnlBonuses = new JPanel();
pnlBonuses.add(new JLabel("Legend:"));
for (int i = 0; i < all.length; i++) {
labels[i] = all[i].name().replace("_", " ").toLowerCase();
abbrs [i] = abbreviate(all[i].name());
c = Colors.values()[i];
but = new JButton(abbrs[i]);
but.setToolTipText(labels[i]);
but.setBackground(c.background(c));
but.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
but.setActionCommand("" + i);
but.addActionListener(this);
pnlBonuses.add(but);
}
}
=== THIS IS A MAJOR EDIT OF WHAT I POSTED AN HOUR AGO ===
I wanted to see if I could implement my own naive method. Here it is:
public class Game implements ActionListener{
public Color [] backgrounds = {TRIPLE_WORD, TRIPLE_LETTER,
DOUBLE_WORD, DOUBLE_LETTER, B_NORMAL};
private void makeScoremasterBonuses(){
String[] labels = {"3W", "3L", "2W", "2L", " "};
JButton but;
pnlBonuses = new JPanel();
pnlBonuses.add(new JLabel("Legend:"));
for (int i = 0; i < labels.length; i++) {
char wt = labels[i].charAt(0);
char tp = labels[i].charAt(1);
but = new JButton(labels[i]);//("" + i);
but.setBackground(backgrounds[i]);
but.setHorizontalAlignment(SwingConstants.CENTER);
but.setActionCommand("" + i);
but.addActionListener(this);
but.setToolTipText("This is a "
+ (i == labels.length - 1 ? "non-bonus" :
(wt == '3' ? "triple" : "double")
+ " " + (tp == 'L' ? "letter" : "word"))
+ " cell.");
pnlBonuses.add(but);
}
}
public void actionPerformed(ActionEvent evt) {
int i = Integer.parseInt(evt.getActionCommand());
Highlighter.shadeSymmetric(currentCell,backgrounds[i]);
}
This has NOW (after edits) EVEN MORE SO been the best thread I've initiated, in terms of quality of responses and all that I've learned because of them. THANK YOU ALL.
BUT I STILL haven't managed to appropriately use setActionCommand. Whatever I did to TRY to use it wound up being so much longer code-wise that I gave up and went for the short and easy but inappropriate.
Any thoughts about how to use set... and getActionCommand the right way (i.e., as Actions) without adding a ton of code to do so?

How to move jslider its start position to end postion automatically when pressing a button in java

I have a code below
jSlider1.setValue(0);
int i =0;
while (i <= jSlider1.getMaximum()) {
jSlider1.setValue(i);
// JOptionPane.showMessageDialog(rootPane,"deded");
Thread.sleep(2000);
i++;
}
What I want is I want to move JSlider automatically its min to max value. I have writeen above code. But I can not get the output. But when I remove the comment of "JOptionPane.showMessageDialog(rootPane,"deded"); " , It's work properly with the message. Please help me. I am in big trouble. I like to have a sample code if any one know the sollution.
Thank you
I am assuming you have create some JPanel or JFrame where you add this slider so,
final JSlider jSlider1 = new JSlider();
jSlider1.setValue(0);
jSlider1.setMaximum(100);
jSlider1.setBounds(0, 50, 300, 50);
final Timer increaseValue = new Timer(50, new ActionListener() {// 50 ms interval in each increase.
public void actionPerformed(ActionEvent e) {
if (jSlider1.getMaximum() != jSlider1.getValue()) {
jSlider1.setValue(jSlider1.getValue() + 1);
} else {
((Timer) e.getSource()).stop();
}
}
});
panel.add(jSlider1);
JButton moveSlider = new JButton("Start");
moveSlider.setBounds(10, 106, 55, 30);
moveSlider.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
increaseValue.start();
}
});
panel.add(moveSlider);

Managing array of labels listeners JAVA GUI

I'm trying to do look alike chess-board in SWT, JAVA.
I tried to do array of buttons, but the color of a button can't be changed (after a long research I have done!).
So I did an array of labels that I can change their color, but now I cannot handle them in one listener, and I don't think that 64 copy-paste listeners are the right thing to do.
However, I found the setActionCommand is not for labels at all.
Do you have any suggestions what can I do to fix that out?
Thanks.
You can use the same Listener for multiple Labels:
public static void main(String[] args)
{
final Display display = new Display();
Shell shell = new Shell(display);
GridLayout layout = new GridLayout(8, true);
layout.horizontalSpacing = 0;
layout.verticalSpacing = 0;
shell.setLayout(layout);
shell.setText("Chess");
/* Define listener once */
Listener listener = new Listener()
{
#Override
public void handleEvent(Event event)
{
/* event.widget is the source of the event */
if(event.widget instanceof Label)
{
System.out.println(event.widget.getData());
}
}
};
for(int i = 0; i < 64; i++)
{
Label label = new Label(shell, SWT.CENTER);
label.setText(i + "");
label.setData(i);
/* Use listener here */
label.addListener(SWT.MouseUp, listener);
label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
Color background = ((i + (i/8))%2 == 0) ? display.getSystemColor(SWT.COLOR_BLACK) : display.getSystemColor(SWT.COLOR_WHITE);
Color foreground = ((i + (i/8))%2 == 0) ? display.getSystemColor(SWT.COLOR_WHITE) : display.getSystemColor(SWT.COLOR_BLACK);
label.setBackground(background);
label.setForeground(foreground);
}
shell.pack();
shell.setSize(200, 200);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
It will print out the Labels data on click.
Looks like this:

Generic Dialog Ok not triggered the second time

i have created a static instance of a generic dialog in my program
static GenericDialog SaveDialog = null;
and below is the code to display the dialog
public boolean DispSaveDialog()
{
//gd.addStringField("Identity : ", "annot");
if(SaveDialog == null)
{
SaveDialog = new GenericDialog("Save");
Panel idnPanel = new Panel();
idnPanel.add(new Label("Identity"));
idnTextComp = new TextField("annot");
csPrefix = idnTextComp.getText();
TextListener tl = new TextListener() {
#Override
public void textValueChanged(TextEvent e) {
// TODO Auto-generated method stub
csPrefix = idnTextComp.getText();
}
};
idnTextComp.addTextListener(tl);
idnPanel.add(idnTextComp);
SaveDialog.addPanel(idnPanel);
final TextComponent textComponent = new TextField();
ActionListener al = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
String label = e.getActionCommand();
//csPrefix = gd.getNextString();
if (label=="Browse")
{
String csFilename = imp.getTitle();
csTextFileName = FileNameProcess( csFilename );
}
textComponent.setText(csTextFileName);
}
};
Button btBrowse = new Button("Browse");
btBrowse.addActionListener(al);
Panel panel = new Panel();
panel.add(new Label("Folder : "));
//textComponent.setBounds(gd.getBounds());
panel.add(textComponent);
panel.add( btBrowse );
SaveDialog.addPanel(panel);
}
SaveDialog.showDialog();
return true;
}
the issue i am facing is, when i open the dialog the second time, the OK and Cancel events are not triggered.
i have a feeling that the issue is silly, sorry and thanks in advance.
The above code was so that when the generic dialog was displayed the second time the old values would be retained..
i did a workaround for the same where i save the strings entered the first time in static string variables and load them after checking for null values.
this is not the solution, just a workaround so i could close the issue on time. :(

When JPanel changes, elements of the old JPanel are left behind

I'm using a JTabbedPane, and on each tab there's a panel, which changes when the user does things like click buttons. The problem I'm getting is that elements from the previous panel get left behind. Usually you can't see them until you run the mouse over them, but sometimes you can't see elements of the new panel until you run your mouse over where they should be. So quite often at first only a little is visible, then:
when you run your mouse over more stuff it becomes visible
Then for some reason when you hit 'multiple choice', which is supposed to create the four new buttons, everything becomes perfectly visible.
I've got repaint(); as pretty much every other line, and before I change anything on the GUI I do removeAll(); first, but it all keeps coming back! Any suggestions? The code for this panel is below, if it might help...
package com.GC01.gui;
import java.awt.Color;
public class PracticeQuizPanel extends JPanel implements MouseListener {
/**
* This panel will allow the user to practice quiz questions.
*/
private static final long serialVersionUID = 1L;
private User user = new User("misha");
boolean isMultipleChoice=false;
boolean usedClue=false;
boolean isStarted=false;
Calendar calendar = Calendar.getInstance();
AnswerAnalysis aA = new AnswerAnalysis();
private Quiz qz = new Quiz( Quiz.getQuestionsFromDisk(), 4, TabbedQuiz.getUser().getNumLogins() );
private JTextArea questionArea;
private JTextArea clueArea;
private JTextArea answerArea;
private JButton clueButton;
private JButton multiButton;
private JButton answerButton;
private JButton startButton;
private int index=0;
private Calendar startCalendar, endCalendar;
private JPanel backPanel;
public PracticeQuizPanel(){
add(new StartButtonPanel());
}
PracticeQuizPanel(int index) {
createVisualElements(index);
}
public void offerAnswer(){
endCalendar = Calendar.getInstance();
aA.setTimeSpent((int) (endCalendar.getTimeInMillis()-startCalendar.getTimeInMillis()));
aA.setRight(answerArea.getText());
JOptionPane.showMessageDialog(null, aA.toString());
answerArea.setEditable(false);
qz.setAnswersAnalysis(index, aA);
index++;
removeAll();
if( index<qz.getLength() ) createVisualElements(index);
else {
removeAll();
JOptionPane.showMessageDialog(null, qz.toFriendlyString());
addQuizResultsToUserProgress();
JOptionPane.showMessageDialog(null, qz.toFriendlyString());
UserProgress uP = new UserProgress(user);
System.out.println(uP.toString());
}
repaint();
startCalendar = Calendar.getInstance();
//JOptionPane.showMessageDialog(null, isStarted);
}
public void addQuizResultsToUserProgress(){
UserProgress userProgress = new UserProgress(user);
ArrayList<AnswerAnalysis> asA = userProgress.getAnswersAnalysis();
for (int i=0; i<qz.getLength(); i++){
asA.add( qz.getAnswersAnalysis()[i]);
}
userProgress.setAnswersAnalysis(asA);
userProgress.saveProgress();
}
/**
* This method creates/recreates all the text boxes, buttons etc. without resetting the quiz and
* the objects in memory.
*/
private void createVisualElements(int index){
if (TabbedQuiz.getUser().getNumLogins()<0)
JOptionPane.showMessageDialog(null, "There was an error. You may have done this quiz before.");
removeAll();
repaint();
startCalendar = Calendar.getInstance();
this.index=index;
setBackground(new Color(112, 128, 144));
setBounds(0,0,728,380);
setLayout(null);
questionArea = new JTextArea();
questionArea.setFont(TabbedQuiz.getDefaultFont().deriveFont(20));//new Font("Courier New", 0, 20));
questionArea.setEditable(false);
questionArea.setLineWrap(true);
questionArea.setWrapStyleWord(true);
questionArea.setBounds(295, 11, 423, 74);
add(questionArea);
//int index=0;
Question q = qz.getQuestions().get(index);
aA = new AnswerAnalysis(q.getQuestionID());
questionArea.setText(q.getQuestionText() );
clueArea = new JTextArea();
clueArea.setFont(TabbedQuiz.getDefaultFont().deriveFont(20));
clueArea.setEditable(false);
clueArea.setLineWrap(true);
clueArea.setWrapStyleWord(true);
clueArea.setBounds(295, 104, 423, 55);
add(clueArea);
JLabel lblQuestion = new JLabel("QUESTION:");
lblQuestion.setFont(TabbedQuiz.getDefaultFont().deriveFont(40));
lblQuestion.setBounds(43, 11, 216, 61);
add(lblQuestion);
answerArea = new JTextArea();//index+"");
answerArea.setFont(TabbedQuiz.getDefaultFont().deriveFont(20));
answerArea.setLineWrap(true);
answerArea.setWrapStyleWord(true);
answerArea.setBounds(295, 301, 423, 50);
answerArea.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER) offerAnswer();
}
});
add(answerArea);
answerArea.setFocusable(true);
answerArea.requestFocusInWindow();
clueButton = new JButton("CLUE?");
clueButton.setFont(TabbedQuiz.getDefaultFont().deriveFont(40));
clueButton.addMouseListener(this);
clueButton.setBounds(15, 104, 244, 55);
add(clueButton);
multiButton = new JButton("MULTIPLE CHOICE?");
multiButton.setFont(TabbedQuiz.getDefaultFont().deriveFont(20));
multiButton.addMouseListener(this);
multiButton.setBounds(15, 195, 244, 55);
add(multiButton);
answerButton = new JButton("ANSWER!");
answerButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
}
});
answerButton.setFont(TabbedQuiz.getDefaultFont().deriveFont(40));
answerButton.setBounds(15, 301, 244, 55);
answerButton.addMouseListener(this);
add(answerButton);
backPanel = new JPanel();
backPanel.setBounds(0, 0, 728, 380);
//add(backPanel);
this.setVisible(true);
repaint();
}
#Override
public void mouseClicked(MouseEvent e) {
if ( e.getSource().equals(startButton) ) {
remove(startButton); repaint(); isStarted=true;
startCalendar = Calendar.getInstance();
}
else if ( e.getSource().equals(answerButton) ) offerAnswer();
else if ( e.getSource().equals(clueButton ) ) {
clueArea.setText(clueArea.getText() + qz.getQuestions().get(index).getClueText() + "\n");
aA.setUsedClue(true);
//JOptionPane.showMessageDialog(null, "hi");
}
else if ( e.getSource().equals(multiButton) ) {
String[] answerOptions = qz.getQuestions().get(index).getAnswerOptions(3);
JButton[] optionsButtons = new JButton[4];
for(int j=0;j<4;j++){
optionsButtons[j]=new JButton(answerOptions[j]);
if(optionsButtons[j].getText().length()>13)
optionsButtons[j].setFont(TabbedQuiz.getDefaultFont().deriveFont(10));
else optionsButtons[j].setFont(TabbedQuiz.getDefaultFont().deriveFont(15));
if(j<2) optionsButtons[j].setBounds(295+211*j , 170, 211, 55);
else optionsButtons[j].setBounds(295+211*(j-2) , 226, 211, 55);
optionsButtons[j].addMouseListener(this);
optionsButtons[j].setName("optionsButton"+"["+j+"]");
add(optionsButtons[j]);
repaint();
}
aA.setMultipleChoice(true);
}
else if ( ( (JButton) e.getSource() ).getName().startsWith("optionsButton") ) {
String answerOffered = ( (JButton) e.getSource() ).getText();
answerArea.setText(answerOffered);
offerAnswer();
}
}
#Override
public void mouseEntered(MouseEvent e) {
if(e.getSource()!=startButton && e.getSource().getClass().equals( answerButton.getClass()) ){
( (JButton) e.getSource() ).setBackground(Color.green);
}if(index>0 && e.getSource()==startButton) remove(startButton);
}
#Override
public void mouseExited(MouseEvent e) {
if(e.getSource()!=startButton && e.getSource().getClass().equals( answerButton.getClass()) ){
( (JButton) e.getSource() ).setBackground(UIManager.getColor("control"));
}
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
}
and on each tab there's a panel, which changes when the user does things like click buttons.
and before I change anything on the GUI I do removeAll();
Whenever I see comments like that it sounds to me like you should be using a Card Layout so you don't have to worry about all these problems.
You need to call revalidate after removing or adding components to a container if using layout managers. Then after that you call repaint.
You've posted a lot of code, and most of it is completely unrelated to the problem at hand, but on the other hand, the code posted is incomplete, won't compile, and thus is not code that we can test. Please next time, try not posting a lot of code that's not relevant to the problem. Try to isolate the problem by continually cutting out code, and then if still stuck, post a minimal compiable program that we can study, test, run, and modify ourselves, an sscce.
I've gone through some of your GUI code (for gosh's sake, not all!), and there's some big time badness there where you're stepping on Swing painting such as this code from ProgressPanel.java:
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
createAndShowGUI(g2d);
// drawDifficultyChart(g2d, fontComboBox.getSelectedIndex());
}
private void createAndShowGUI(Graphics2D g2d) {
JButton showChartButton = new JButton("Show new chart!");
user = TabbedQuiz.getUser();
showChartButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
if (categoryComboBox.getSelectedIndex() == 0
&& difficultyComboBox.getSelectedIndex() != 0) {
drawDifficultyChart((Graphics2D) getGraphics(),
difficultyComboBox.getSelectedIndex());
} else if (difficultyComboBox.getSelectedIndex() == 0
&& categoryComboBox.getSelectedIndex() != 0) {
drawCategoryChart((Graphics2D) getGraphics(),
(String) categoryComboBox.getSelectedItem());
} else
drawGeneralChart((Graphics2D) getGraphics(),
(String) categoryComboBox.getSelectedItem(),
difficultyComboBox.getSelectedIndex());
} catch (NullPointerException e1) {
JOptionPane.showMessageDialog(null, "Sign in first.");
}
}
});
showChartButton.setBounds(10, 90, 96, 26);
showChartButton.setFont(font);
add(showChartButton);
}
The problem is that you're creating and adding components to a container from within a paint/paintComponent method, something you should never be doing and something that is bound to mess up your program's graphics.
To anyone else with this issue: I eventually solved the problem. setVisible(false); setVisible(true);. Put it EVERYWHERE.

Categories