I have some custom JPanels that are used as buttons. This works well 90% of the time, however, sometimes the GUI doesn't respond to a mouse click - the mouseClicked event is not triggered and you have to click again (sometimes even more than once) to actually trigger it.
This behavior appears to be random, though I have the feeling that it occurs more frequently after having moved the frame to another monitor.
Here is the code:
public class EatingMouse extends JFrame implements MouseListener {
JPanel contentPane;
int contentPanelWidth, contentPanelHeight;
int mainTabMarginHeight, mainTabMarginWidth;
int subTabMarginHeight, subTabMarginWidth;
Color fontColor = Color.WHITE;
Color tabBackgroundColor = Color.BLACK;
Color tabBackgroundHighlightColor = Color.GRAY;
Color tabBackgroundSelectedColor = Color.LIGHT_GRAY;
TabPanel firstMainTab;
TabPanel secondMainTab;
ArrayList<TabPanel> firstSubTabs;
ArrayList<TabPanel> secondSubTabs;
ArrayList<TabPanel> currentSubTabs;
int clickCounter;
public EatingMouse() {
super("Why do you eat mouse clicks?");
JLayeredPane layeredPane = new JLayeredPane();
firstMainTab = new TabPanel("First Tab", 18);
firstMainTab.addMouseListener(this);
layeredPane.add(firstMainTab, new Integer(100));
secondMainTab = new TabPanel("Second Tab", 18);
secondMainTab.addMouseListener(this);
layeredPane.add(secondMainTab, new Integer(100));
firstSubTabs = new ArrayList<>();
secondSubTabs = new ArrayList<>();
currentSubTabs = new ArrayList<>();
TabPanel tp = new TabPanel("First First Subtab", 14);
tp.addMouseListener(this);
layeredPane.add(tp, new Integer(100));
firstSubTabs.add(tp);
tp = new TabPanel("Second First Subtab", 14);
tp.addMouseListener(this);
layeredPane.add(tp, new Integer(100));
firstSubTabs.add(tp);
tp = new TabPanel("First Second Subtab", 14);
tp.addMouseListener(this);
layeredPane.add(tp, new Integer(100));
secondSubTabs.add(tp);
tp = new TabPanel("Second Second Subtab", 14);
tp.addMouseListener(this);
layeredPane.add(tp, new Integer(100));
secondSubTabs.add(tp);
contentPane = new JPanel(new BorderLayout());
setContentPane(contentPane);
contentPane.add(layeredPane);
mainTabMarginWidth = 40;
mainTabMarginHeight = 8;
subTabMarginWidth = 20;
subTabMarginHeight = 10;
selectTabs(0, 1);
clickCounter = 0;
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(new Dimension(800, 600));
setVisible(true);
}
public void selectTabs(int mainTab, int subTab) {
boolean hasChanged = false;
if((mainTab == 0) && !firstMainTab.isSelected) {
hasChanged = true;
firstMainTab.setSelected(true);
secondMainTab.setSelected(false);
for(TabPanel tp : currentSubTabs) {
tp.setSelected(false);
tp.setVisible(false);
}
currentSubTabs = firstSubTabs;
for(TabPanel tp : currentSubTabs) {
tp.setVisible(true);
}
currentSubTabs.get(subTab).setSelected(true);
}
else if((mainTab == 1) && !secondMainTab.isSelected) {
hasChanged = true;
firstMainTab.setSelected(false);
secondMainTab.setSelected(true);
for(TabPanel tp : currentSubTabs) {
tp.setSelected(false);
tp.setVisible(false);
}
currentSubTabs = secondSubTabs;
for(TabPanel tp : currentSubTabs) {
tp.setVisible(true);
}
currentSubTabs.get(subTab).setSelected(true);
}
else if((mainTab == 0) && firstMainTab.isSelected) {
hasChanged = true;
for(TabPanel tp : currentSubTabs) {
if(tp != currentSubTabs.get(subTab)) { tp.setSelected(false); }
else { tp.setSelected(true); }
}
}
else if((mainTab == 1) && secondMainTab.isSelected) {
hasChanged = true;
for(TabPanel tp : currentSubTabs) {
if(tp != currentSubTabs.get(subTab)) { tp.setSelected(false); }
else { tp.setSelected(true); }
}
}
if(hasChanged) {
revalidate();
repaint();
}
}
#Override
public void paint(Graphics graphics) {
super.paint(graphics);
contentPanelWidth = getContentPane().getWidth();
contentPanelHeight = getContentPane().getHeight();
int xOffset = 100;
int yOffset = 100;
FontMetrics mainTabMetrics = graphics.getFontMetrics(firstMainTab.label.getFont());
firstMainTab.setBounds(xOffset, yOffset, (mainTabMetrics.stringWidth(firstMainTab.text) + mainTabMarginWidth), (mainTabMetrics.getHeight() + mainTabMarginHeight));
xOffset += firstMainTab.getBounds().width;
secondMainTab.setBounds(xOffset, yOffset, (mainTabMetrics.stringWidth(secondMainTab.text) + mainTabMarginWidth), (mainTabMetrics.getHeight() + mainTabMarginHeight));
FontMetrics subTabMetrics = graphics.getFontMetrics(currentSubTabs.get(0).label.getFont());
xOffset = 100;
yOffset += firstMainTab.getBounds().height;
for(TabPanel tp : currentSubTabs) {
tp.setBounds(xOffset, yOffset, (subTabMetrics.stringWidth(tp.text) + subTabMarginWidth), (subTabMetrics.getHeight() + subTabMarginHeight));
tp.revalidate();
tp.repaint();
xOffset += tp.getBounds().width;
}
}
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("click " + clickCounter++);
Object source = e.getSource();
if(source == firstMainTab && !firstMainTab.isSelected) {
secondMainTab.setSelected(false);
if(currentSubTabs.get(1).isSelected) { selectTabs(0, 1); }
else { selectTabs(0, 0); }
}
else if(source == secondMainTab && !secondMainTab.isSelected) {
if(currentSubTabs.get(1).isSelected) { selectTabs(1, 1); }
else { selectTabs(1, 0); }
}
}
#Override
public void mouseEntered(MouseEvent e) {
Object source = e.getSource();
if(source == firstMainTab && !firstMainTab.isSelected) { firstMainTab.setBackground(tabBackgroundHighlightColor); }
else if(source == secondMainTab && !secondMainTab.isSelected) { secondMainTab.setBackground(tabBackgroundHighlightColor); }
else if(currentSubTabs.contains(source) && !((TabPanel) source).isSelected) {
((TabPanel)source).setBackground(tabBackgroundHighlightColor);
}
}
#Override
public void mouseExited(MouseEvent e) {
Object source = e.getSource();
if(source == firstMainTab && !firstMainTab.isSelected) { firstMainTab.setBackground(tabBackgroundColor); }
else if(source == secondMainTab && !secondMainTab.isSelected) { secondMainTab.setBackground(tabBackgroundColor); }
else if(currentSubTabs.contains(source) && !((TabPanel) source).isSelected) {
((TabPanel)source).setBackground(tabBackgroundColor);
}
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
public class TabPanel extends JPanel {
JLabel label;
String text;
boolean isSelected;
public TabPanel(String labelText, int fontSize) {
super();
text = labelText;
isSelected = false;
setLayout(new GridBagLayout());
setBackground(tabBackgroundColor);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.PAGE_START;
gbc.fill = GridBagConstraints.BOTH;
gbc.weighty = 0.1;
gbc.weightx = 0.1;
gbc.insets = new Insets(0,0,0,0);
label = new JLabel("<html><div style=\"text-align:center\"> " + text + "</div></html>", SwingConstants.CENTER);
label.setAlignmentX(JLabel.CENTER_ALIGNMENT);
label.setForeground(fontColor);
label.setFont(new Font("Arial", Font.BOLD, fontSize));
add(label, gbc);
}
public void setSelected(boolean selected) {
isSelected = selected;
if(selected) { setBackground(tabBackgroundSelectedColor); }
else { setBackground(tabBackgroundColor); }
}
public boolean isSelected() { return isSelected; }
#Override
public String toString() {
return text + " - " + label.getFont().getSize();
}
}
public static void main(String[] args) {
new EatingMouse();
}
}
Please note that I have chosen JPanels as buttons because I want to heavily customize them later, which I didn't get to work with extending JButton.
Thank you for your time reading this and of course I would appreciate any leads on why this is happening and what I can do to improve this code.
Related
I had an issue with a piece of code I was writing where I was adding JPanel's inside of others to form a layout. The issue is that after the window is displayed I needed to get the x and y coordinates of one of the text fields but whenever I try using the getX() and getY() methods they keep returning 0. I have verified that the getX() and getY() methods are being called after the window is initialized and displayed. How can I fix this and get the actual coordinates of the text field.
This is window code:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
public class GraphicsPanel extends JFrame implements ActionListener, CaretListener{
JPanel buttonPanel = new JPanel();
JPanel mainPanel = new JPanel();
JPanel animationPanel = new JPanel();
JPanel bottomPanel = new JPanel();
JPanel text = new JPanel();
PokemonLearnsets info = new PokemonLearnsets();
HealthBar healthBar1 = new HealthBar();
HealthBar healthBar2 = new HealthBar();
JTextArea textArea = new JTextArea();
JTextField response = new JTextField();
int health1 = 100;
int total1 = 100;
int health2 = 100;
int total2 = 100;
int startOfRect = 1;
int p1MonNum = -1;
int waitTime = 20;
int p2MonNum = -1;
TextInterface theText;
Icon allIcons[][];
JLabel p1Gif;
JLabel p2Gif;
JPanel mainBuilderPanel = new JPanel();
JPanel builderPanel = new JPanel();
JPanel builderMessagePanel = new JPanel();
JPanel monPanels [] = new JPanel[6];
JPanel imagePanels[] = new JPanel[6];
JPanel namePanels[] = new JPanel[6];
JPanel movePanels[] = new JPanel[6];
JPanel allMoves[][] = new JPanel[6][4];
JTextField names[] = new JTextField[6];
JTextField moves[][] = new JTextField[6][4];
JButton validate = new JButton("Validate");
JLabel tempImages[] = new JLabel[6];
JLabel emptyLabels[] = new JLabel[6];
AutoSuggestor [] nameSuggestions = new AutoSuggestor[6];
AutoSuggestor [][] moveSuggestions = new AutoSuggestor[6][4];
public GraphicsPanel(String name){
super(name);
setupTeamBuilderPanel();
// setupBattlePanel();
}
private void setupTeamBuilderPanel() {
Container c = getContentPane();
mainBuilderPanel.setLayout(new BorderLayout());
mainBuilderPanel.setBorder(new LineBorder(Color.BLACK, 2));
builderPanel.setLayout(new GridLayout(1, 0));
builderPanel.setBorder(new LineBorder(Color.BLACK, 1));
builderMessagePanel.setBorder(new LineBorder(Color.BLACK, 2));
for (int i = 0; i < monPanels.length; i ++) {
monPanels[i] = new JPanel();
imagePanels[i] = new JPanel();
namePanels[i] = new JPanel();
movePanels[i] = new JPanel();
names[i] = new JTextField();
names[i].addCaretListener(this);
emptyLabels[i] = new JLabel();
tempImages[i] = emptyLabels[i];
monPanels[i].setBorder(new LineBorder(Color.BLACK, 3));
imagePanels[i].setBorder(new LineBorder(Color.BLACK, 3));
movePanels[i].setBorder(new LineBorder(Color.BLACK, 3));
monPanels[i].setLayout(new GridLayout(0 ,1));
namePanels[i].setLayout(new GridLayout(1, 0));
movePanels[i].setLayout(new GridLayout(0, 1));
imagePanels[i].setLayout(new BorderLayout());
namePanels[i].add(new JLabel(" Name:"));
namePanels[i].add(names[i]);
imagePanels[i].add(tempImages[i]);
imagePanels[i].add(namePanels[i], BorderLayout.SOUTH);
monPanels[i].add(imagePanels[i]);
for (int k = 0; k < moves[i].length; k ++) {
moves[i][k] = new JTextField();
allMoves[i][k] = new JPanel();
allMoves[i][k].setLayout(new GridLayout(0, 1));
allMoves[i][k].add(new JLabel(" Move " + Integer.toString(k + 1) + ":"));
allMoves[i][k].add(moves[i][k]);
allMoves[i][k].add(new JLabel());
allMoves[i][k].add(new JLabel());
movePanels[i].add(allMoves[i][k]);
}
monPanels[i].add(movePanels[i]);
builderPanel.add(monPanels[i]);
}
String welcomeMessage = "";
for (int i = 0; i < 5; i ++) {
welcomeMessage += " ";
}
welcomeMessage += "Welcome to the Teambuilder!";
setupSuggestions();
validate.addActionListener(this);
builderMessagePanel.add(new JLabel(welcomeMessage));
mainBuilderPanel.add(builderMessagePanel, BorderLayout.NORTH);
mainBuilderPanel.add(validate, BorderLayout.SOUTH);
mainBuilderPanel.add(builderPanel);
c.add(mainBuilderPanel);
}
private void setupBattlePanel() {
Container c = getContentPane();
mainPanel.setLayout(new GridLayout());
bottomPanel.setLayout(new GridLayout());
animationPanel.setBorder(new LineBorder(Color.BLACK, 3));
animationPanel.setLayout(new GridLayout(0, 2));
mainPanel.add(animationPanel);
buttonPanel.setBorder(new LineBorder(Color.BLACK, 3));
buttonPanel.setLayout(new FlowLayout(5));
buttonPanel.setBackground(Color.GREEN);
// buttonPanel.add(new JLabel(" "));
// buttonPanel.add(new JButton("Testing"));
// buttonPanel.add(new JButton("Testing"));
// buttonPanel.add(new JButton("Testing"));
// buttonPanel.add(new JButton("Testing"));
bottomPanel.add(buttonPanel);
text.setLayout(new GridLayout());
text.setBorder(new LineBorder(Color.BLACK, 3));
text.add(response);
bottomPanel.add(text);
textArea.setWrapStyleWord(true);
textArea.setLineWrap(true);
textArea.setEditable(false);
textArea.setBackground(Color.LIGHT_GRAY);
JScrollPane textAreaPane = new JScrollPane(textArea, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
textAreaPane.setBorder(new LineBorder(Color.BLACK, 3));
mainPanel.add(textAreaPane);
c.add(mainPanel, BorderLayout.CENTER);
c.add(bottomPanel, BorderLayout.SOUTH);
}
private void setupSuggestions() {
ArrayList<String> allPossibleMoves = new ArrayList<String>();
Collections.addAll(allPossibleMoves, info.getAllMoves());
for (int i = 0; i < 6; i ++) {
for (int k = 0; k < 4; k ++) {
moveSuggestions[i][k] = new AutoSuggestor(moves[i][k], allPossibleMoves, Color.WHITE.brighter(), Color.BLACK, Color.BLACK, 0.75f);
moveSuggestions[i][k].setTextField(moves[i][k]);
}
}
}
public void writeToScreen(String writing) {
String current = textArea.getText();
textArea.setText(current + writing);
}
public void updateAll() {
mainPanel.updateUI();
bottomPanel.updateUI();
mainBuilderPanel.updateUI();
}
public void setTextInterface(TextInterface text) {
theText = text;
response.addActionListener(theText.action);
}
public void drawMons(String name1, String name2) {
animationPanel.removeAll();
ImageIcon secImage = new ImageIcon(this.getClass().getResource("SpritesFront/" + name2 + ".gif"));
secImage = new ImageIcon(secImage.getImage().getScaledInstance((int)(secImage.getIconWidth() * 1.5), (int)(secImage.getIconHeight() * 1.5), Image.SCALE_DEFAULT));
Icon icon = secImage;
p2Gif = new JLabel(icon);
ImageIcon firstImage = new ImageIcon(this.getClass().getResource("SpritesBack/" + name1 + "-back.gif"));
firstImage = new ImageIcon(firstImage.getImage().getScaledInstance((int)(firstImage.getIconWidth() * 1.5), (int)(firstImage.getIconHeight() * 1.5), Image.SCALE_DEFAULT));
Icon icon2 = firstImage;
p1Gif = new JLabel(icon2);
animationPanel.add(healthBar2);
animationPanel.add(p2Gif);
animationPanel.add(p1Gif);
animationPanel.add(healthBar1);
updateAll();
}
public void fillPortions(int x) {
JLabel [] labels = new JLabel[x];
for (int i = 0; i < x; i ++) {
labels[i] = new JLabel();
animationPanel.add(labels[i]);
}
}
public void refreshHealthBar(int health, int total, int pNum, int mon) {
if (pNum == 1) {
if (p1MonNum != mon && p1MonNum != -1) {
p1MonNum = mon;
health1 = health;
total1 = total;
healthBar1.setHealth(health);
healthBar1.setTotal(total);
redoHealthPanel();
}
else {
p1MonNum = mon;
healthBar1.setTotal(total);;
while (health < health1) {
healthBar1.setHealth(health1);
redoHealthPanel();
health1--;
}
while (health > health1) {
healthBar1.setHealth(health1);
redoHealthPanel();
health1++;
}
}
}
else {
if (p2MonNum != mon && p2MonNum != -1) {
p2MonNum = mon;
health2 = health;
total2 = total;
healthBar2.setHealth(health);
healthBar2.setTotal(total);
redoHealthPanel();
updateAll();
}
else {
p2MonNum = mon;
healthBar2.setTotal(total);
while (health < health2) {
healthBar2.setHealth(health2);
redoHealthPanel();
health2--;
}
while (health > health2) {
healthBar2.setHealth(health2);
redoHealthPanel();
health2++;
}
}
}
}
private void redoHealthPanel () {
animationPanel.removeAll();
animationPanel.add(healthBar2);
animationPanel.add(p2Gif);
animationPanel.add(p1Gif);
animationPanel.add(healthBar1);
updateAll();
try {
TimeUnit.MILLISECONDS.sleep(waitTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private String validatePokemon() {
String answer = "";
String tempMonNames [] = new String[6];
boolean invalidMove = false;
for (int i = 0; i < monPanels.length; i ++) {
String currentName = names[i].getText();
if (currentName.isEmpty()) {
answer = "You must have 6 Pokemon on your team but you can have less than 4 moves";
return answer;
}
for (String element : tempMonNames) {
if (element == null) {
continue;
} else if (currentName.equals(element)) {
answer = "You have duplicate Pokemon on your team";
return answer;
}
}
if (!info.validPokemon(currentName)) {
answer += "Pokemon #" + (i + 1) + " is invalid\n";
} else {
tempMonNames[i] = currentName;
}
int count = 0;
for (int k = 0; k < moves[i].length; k++) {
if (moves[i][k].getText().isEmpty()) {
count++;
}
if (!info.validMove(moves[i][k].getText().replace(" ", "").toLowerCase(), currentName)) {
answer += "Pokemon #" + (i + 1) + ", move #" + (k + 1) + " is invalid\n";
invalidMove = true;
}
if (count >= 4) {
answer += "Pokemon #" + (i + 1) + " has no moves\n";
break;
}
}
}
if (invalidMove) {
answer += "***Please keep in mind only damaging moves without recoil are allowed, if there aren't enough for 4 moves, leave fields blank***";
}
return answer;
}
#Override
public void actionPerformed(ActionEvent e) {
if (validatePokemon().isEmpty()) {
JOptionPane.showMessageDialog(null, "Confirmed" , "", JOptionPane.INFORMATION_MESSAGE);
} else {
JOptionPane.showMessageDialog(null, validatePokemon() , "", JOptionPane.ERROR_MESSAGE);
}
}
#Override
public void caretUpdate(CaretEvent e) {
for (int i = 0; i < names.length; i ++) {
if (info.validPokemon(names[i].getText()) && tempImages[i].getParent() == null) {
ImageIcon temp = new ImageIcon(this.getClass().getResource("SpritesFront/" + names[i].getText().replace(" ", "").replace(":", "").replace("'", "").replace(".", "").replace("-", "").toLowerCase() + ".gif"));
temp = new ImageIcon(temp.getImage().getScaledInstance((int)(temp.getIconWidth() * 1.5), (int)(temp.getIconHeight() * 1.5), Image.SCALE_DEFAULT));
Icon icon = temp;
imagePanels[i].remove(tempImages[i]);
tempImages[i] = new JLabel(icon);
imagePanels[i].add(tempImages[i]);
updateAll();
} else if (!info.validPokemon(names[i].getText())){
imagePanels[i].remove(tempImages[i]);
updateAll();
}
}
}
}
This is set up for the window:
GraphicsPanel window = new GraphicsPanel("Pokemon");
window.setBounds(0, 0, 1440, 830);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
This is where the getX() and getY() are getting called:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.*;
import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
public class AutoSuggestor {
private final JTextComponent textComp;
private JPanel suggestionsPanel;
private JWindow autoSuggestionPopUpWindow;
private String typedWord;
private final ArrayList<String> dictionary = new ArrayList<>();
private JTextField textField;
private int currentIndexOfSpace, tW, tH;
private DocumentListener documentListener = new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent de) {
checkForAndShowSuggestions();
}
#Override
public void removeUpdate(DocumentEvent de) {
checkForAndShowSuggestions();
}
#Override
public void changedUpdate(DocumentEvent de) {
checkForAndShowSuggestions();
}
};
private final Color suggestionsTextColor;
private final Color suggestionFocusedColor;
public AutoSuggestor(JTextComponent textComp, ArrayList<String> words, Color popUpBackground, Color textColor, Color suggestionFocusedColor, float opacity) {
this.textComp = textComp;
this.suggestionsTextColor = textColor;
this.suggestionFocusedColor = suggestionFocusedColor;
this.textComp.getDocument().addDocumentListener(documentListener);
setDictionary(words);
typedWord = "";
currentIndexOfSpace = 0;
tW = 0;
tH = 0;
autoSuggestionPopUpWindow = new JWindow();
autoSuggestionPopUpWindow.setOpacity(opacity);
suggestionsPanel = new JPanel();
suggestionsPanel.setLayout(new GridLayout(0, 1));
suggestionsPanel.setBackground(popUpBackground);
addKeyBindingToRequestFocusInPopUpWindow();
}
private void addKeyBindingToRequestFocusInPopUpWindow() {
textComp.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "Down released");
textComp.getActionMap().put("Down released", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent ae) {//focuses the first label on popwindow
for (int i = 0; i < suggestionsPanel.getComponentCount(); i++) {
if (suggestionsPanel.getComponent(i) instanceof SuggestionLabel) {
((SuggestionLabel) suggestionsPanel.getComponent(i)).setFocused(true);
autoSuggestionPopUpWindow.toFront();
autoSuggestionPopUpWindow.requestFocusInWindow();
suggestionsPanel.requestFocusInWindow();
suggestionsPanel.getComponent(i).requestFocusInWindow();
break;
}
}
}
});
suggestionsPanel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "Down released");
suggestionsPanel.getActionMap().put("Down released", new AbstractAction() {
int lastFocusableIndex = 0;
#Override
public void actionPerformed(ActionEvent ae) {//allows scrolling of labels in pop window (I know very hacky for now :))
ArrayList<SuggestionLabel> sls = getAddedSuggestionLabels();
int max = sls.size();
if (max > 1) {//more than 1 suggestion
for (int i = 0; i < max; i++) {
SuggestionLabel sl = sls.get(i);
if (sl.isFocused()) {
if (lastFocusableIndex == max - 1) {
lastFocusableIndex = 0;
sl.setFocused(false);
autoSuggestionPopUpWindow.setVisible(false);
setFocusToTextField();
checkForAndShowSuggestions();//fire method as if document listener change occured and fired it
} else {
sl.setFocused(false);
lastFocusableIndex = i;
}
} else if (lastFocusableIndex <= i) {
if (i < max) {
sl.setFocused(true);
autoSuggestionPopUpWindow.toFront();
autoSuggestionPopUpWindow.requestFocusInWindow();
suggestionsPanel.requestFocusInWindow();
suggestionsPanel.getComponent(i).requestFocusInWindow();
lastFocusableIndex = i;
break;
}
}
}
} else {//only a single suggestion was given
autoSuggestionPopUpWindow.setVisible(false);
setFocusToTextField();
checkForAndShowSuggestions();//fire method as if document listener change occured and fired it
}
}
});
}
private void setFocusToTextField() {
textComp.requestFocusInWindow();
}
public ArrayList<SuggestionLabel> getAddedSuggestionLabels() {
ArrayList<SuggestionLabel> sls = new ArrayList<>();
for (int i = 0; i < suggestionsPanel.getComponentCount(); i++) {
if (suggestionsPanel.getComponent(i) instanceof SuggestionLabel) {
SuggestionLabel sl = (SuggestionLabel) suggestionsPanel.getComponent(i);
sls.add(sl);
}
}
return sls;
}
private void checkForAndShowSuggestions() {
typedWord = getCurrentlyTypedWord();
suggestionsPanel.removeAll();//remove previos words/jlabels that were added
//used to calcualte size of JWindow as new Jlabels are added
tW = 0;
tH = 0;
boolean added = wordTyped(typedWord);
if (!added) {
if (autoSuggestionPopUpWindow.isVisible()) {
autoSuggestionPopUpWindow.setVisible(false);
}
} else {
showPopUpWindow();
setFocusToTextField();
}
}
protected void addWordToSuggestions(String word) {
SuggestionLabel suggestionLabel = new SuggestionLabel(word, suggestionFocusedColor, suggestionsTextColor, this);
calculatePopUpWindowSize(suggestionLabel);
suggestionsPanel.add(suggestionLabel);
}
public String getCurrentlyTypedWord() {//get newest word after last white spaceif any or the first word if no white spaces
String text = textComp.getText();
String wordBeingTyped = "";
text = text.replaceAll("(\\r|\\n)", " ");
if (text.contains(" ")) {
int tmp = text.lastIndexOf(" ");
if (tmp >= currentIndexOfSpace) {
currentIndexOfSpace = tmp;
wordBeingTyped = text.substring(text.lastIndexOf(" "));
}
} else {
wordBeingTyped = text;
}
return wordBeingTyped.trim();
}
private void calculatePopUpWindowSize(JLabel label) {
//so we can size the JWindow correctly
if (tW < label.getPreferredSize().width) {
tW = label.getPreferredSize().width;
}
tH += label.getPreferredSize().height;
}
public void setTextField(JTextField textField) {
this.textField = textField;
}
private void showPopUpWindow() {
autoSuggestionPopUpWindow.getContentPane().add(suggestionsPanel);
autoSuggestionPopUpWindow.setMinimumSize(new Dimension(textComp.getWidth(), 30));
autoSuggestionPopUpWindow.setSize(tW, tH);
autoSuggestionPopUpWindow.setVisible(true);
//show the pop up
autoSuggestionPopUpWindow.setLocation(textComp.getX(), textComp.getY() + textComp.getHeight());
autoSuggestionPopUpWindow.setMinimumSize(new Dimension(textComp.getWidth(), 30));
autoSuggestionPopUpWindow.revalidate();
autoSuggestionPopUpWindow.repaint();
}
public void setDictionary(ArrayList<String> words) {
dictionary.clear();
if (words == null) {
return;//so we can call constructor with null value for dictionary without exception thrown
}
for (String word : words) {
dictionary.add(word);
}
}
public JWindow getAutoSuggestionPopUpWindow() {
return autoSuggestionPopUpWindow;
}
public JTextComponent getTextField() {
return textComp;
}
public void addToDictionary(String word) {
dictionary.add(word);
}
boolean wordTyped(String typedWord) {
if (typedWord.isEmpty()) {
return false;
}
//System.out.println("Typed word: " + typedWord);
boolean suggestionAdded = false;
for (String word : dictionary) {//get words in the dictionary which we added
boolean fullymatches = true;
for (int i = 0; i < typedWord.length(); i++) {//each string in the word
if (!typedWord.toLowerCase().startsWith(String.valueOf(word.toLowerCase().charAt(i)), i)) {//check for match
fullymatches = false;
break;
}
}
if (fullymatches) {
addWordToSuggestions(word);
suggestionAdded = true;
}
}
return suggestionAdded;
}
}
class SuggestionLabel extends JLabel {
private boolean focused = false;
private final JWindow autoSuggestionsPopUpWindow;
private final JTextComponent textComponent;
private final AutoSuggestor autoSuggestor;
private Color suggestionsTextColor, suggestionBorderColor;
public SuggestionLabel(String string, final Color borderColor, Color suggestionsTextColor, AutoSuggestor autoSuggestor) {
super(string);
this.suggestionsTextColor = suggestionsTextColor;
this.autoSuggestor = autoSuggestor;
this.textComponent = autoSuggestor.getTextField();
this.suggestionBorderColor = borderColor;
this.autoSuggestionsPopUpWindow = autoSuggestor.getAutoSuggestionPopUpWindow();
initComponent();
}
private void initComponent() {
setFocusable(true);
setForeground(suggestionsTextColor);
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent me) {
super.mouseClicked(me);
replaceWithSuggestedText();
autoSuggestionsPopUpWindow.setVisible(false);
}
});
getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, true), "Enter released");
getActionMap().put("Enter released", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent ae) {
replaceWithSuggestedText();
autoSuggestionsPopUpWindow.setVisible(false);
}
});
}
public void setFocused(boolean focused) {
if (focused) {
setBorder(new LineBorder(suggestionBorderColor));
} else {
setBorder(null);
}
repaint();
this.focused = focused;
}
public boolean isFocused() {
return focused;
}
private void replaceWithSuggestedText() {
String suggestedWord = getText();
String text = textComponent.getText();
String typedWord = autoSuggestor.getCurrentlyTypedWord();
String t = text.substring(0, text.lastIndexOf(typedWord));
String tmp = t + text.substring(text.lastIndexOf(typedWord)).replace(typedWord, suggestedWord);
textComponent.setText(tmp);
}
}
The textComp.getX() and textComp.getY() in the showPopUpWindow method are the ones that are giving zeros.
After thinking about it for a while I came up with this solution and it works for me.
int x = 0;
int y = 0;
Component currentComponent = textComp;
while (currentComponent != null) {
x += currentComponent.getX();
y += currentComponent.getY();
currentComponent = currentComponent.getParent();
}
I have a Swing Form (Java). In this form I have field, for example Name1. I initialize it so:
private JTextField Name1;
In this code i'm adding JTextField Name1 into my Form:
tabbedPane.addTab("T6", null, panel, "T6");
panel.setLayout(null);
Name1.setBounds(73, 11, 674, 20);
panel.add(Name1);
Additionaly I have Button1 on my form. The event in this button is changing the value of Name1. Its work normaly.
Moreover I have a Button 2 that hiding the Tab with Name1:
tabbedPane.remove(1);
tabbedPane.repaint();
tabbedPane.revalidate();
frame.repaint();
frame.revalidate();
(And, of course, I turn on my tabpane again after this)
After all that, by the pressing the Button 4 I want to change the vlue of Name1 to some text.
But it doesn't work!!!!!! SetTex doesnt work. The field is empty.
So, if I change the Name1 declaration from
private JTextField Name1;
to
static JTextField Name1;
Yes, it works. BUT! Then I can't change the value of Name1 by using
Name1.Settext("Example");
What i have to do to make Name1 available after Button 4 pressed and changable ????
The all code is:
public class GUI {
public JTextField Name_textField;
public static void main(String[] args) {
DB_Initialize();
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GUI window = new GUI();
window.frame.setVisible(true);
window.frame.setResizable(false);
FirstConnect FC = window.new FirstConnect();
ConnectStatus = true;
FC.FirstEntry();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public GUI() {
CurrentEnty_textField = new JTextField();
Name_textField = new JTextField();
EntriesCountlbl = new JLabel("New label");
initialize();
EntriesCountlbl.setText(Integer.toString(EC1));
if (LoginStatus == true) {
System.out.println("LoginStatus == true");
AdminPartOn();
btnNewButton.setEnabled(false);
} else {
btnNewButton_3.setEnabled(false);
tabbedPane.setEnabledAt(1, false);
// UnableForm();
AdminPartOff();
}
}
public static void DB_Initialize() {
conn3 = con3.DoConnect();
int ID;
ArrayList<String> list = new ArrayList<String>();
String l;
String p;
list = con3.LoginFileRead();
if (list.size() == 2) {
l = list.get(0);
p = list.get(1);
System.out.println("Логин из файла = " + l);
System.out.println("Пароль из файла = " + p);
ID = con3.CRMUserRequest(conn3, l, p);
AdminPanelData = con3.CRMUserFullData(conn3, l, p);
if (ID != 0) {
System.out.println("ID Юзера = " + ID);
LoginStatus = true;
}
}
EC1 = con3.CRMQuery_EntriesCount(conn3); // запрашиваем кол-во записей
StatusTableEntriesCount = con3.CRMQueryStatus_EntriesCount(conn3);
StatusTableFromCount = con3.CRMQueryFRom_EntriesCount(conn3);
System.out.println("Entries count(Из модуля GYU): " + EC1);
if (EC1 > 0) {
CurrentEntry = 1;
System.out.println("Все ОК, текущая запись - " + CurrentEntry);
} else {
System.out.println("Выскакивает обработчик ошибок");
}
con3.Ini();
con3.CRMQuery2(conn3, EC1 + 1);
StatusColumn = con3.CRMQueryStatus(conn3, StatusTableEntriesCount);
FromColumn = con3.CRMQueryFrom(conn3, StatusTableFromCount);
}
public class FirstConnect {
public void FirstEntry() {
int CurStatus = F.GetStatus(CurrentEntry - 1);
int CurFrom = F.GetFrom(CurrentEntry - 1);
if (LoginStatus != false) {
Name_textField.setText(F.GetName(CurrentEntry - 1));
} else {
Name_textField.setText("-");
}
}
}
private void initialize() {
frame = new JFrame();
panel = new JPanel();
frame.setBounds(100, 100, 816, 649);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
tabbedPane = new JTabbedPane(JTabbedPane.TOP);
tabbedPane.setBounds(10, 250, 780, 361);
frame.getContentPane().add(tabbedPane);
JPanel panel_1 = new JPanel();
tabbedPane.addTab("\u0412\u0445\u043E\u0434", null, panel_1, null);
btnNewButton = new JButton("\u0412\u0445\u043E\u0434");
btnNewButton.setBounds(263, 285, 226, 37);
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int ID;
ID = con3.CRMUserRequest(conn3, LoginField.getText(), PasswordField.getText());
if (ID == 0) {
} else {
MainTab();
FirstEntry3();
}
}
});
panel_1.setLayout(null);
panel_1.add(btnNewButton);
tabbedPane.addTab("\u041A\u043B\u0438\u0435\u043D\u0442", null, panel,
"\u041A\u043E\u043D\u0442\u0430\u043A\u0442\u043D\u044B\u0435 \u0434\u0430\u043D\u043D\u044B\u0435 \u043A\u043B\u0438\u0435\u043D\u0442\u0430");
panel.setLayout(null);
// Name_textField = new JTextField();
Name_textField.setBounds(73, 11, 674, 20);
panel.add(Name_textField);
Name_textField.setHorizontalAlignment(SwingConstants.CENTER);
Name_textField.setColumns(10);
NextEntryButton.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (NextEntryButton.isEnabled() != false) {
if (CurrentEntry < EC1) {
CurrentEntry = CurrentEntry + 1;
int CurStatus = F.GetStatus(CurrentEntry - 1);
int CurFrom = F.GetFrom(CurrentEntry - 1);
Name_textField.setText(F.GetName(CurrentEntry - 1));
} else {
}
}
}
});
}
public void MainTab() {
tabbedPane.addTab("1", null, panel,
"1");
tabbedPane.setEnabledAt(1, true);
panel.setLayout(null);
}
public void FirstEntry3() {
Name_textField.setText(F.GetName(CurrentEntry - 1));
}
}
however I am not sure where I am supposed to enter the whoWins() method. Do I enter this method in the actionperformed Method of the buttons or do i need to something different. Please help.
public class TTT extends JFrame implements ActionListener {
private JButton buttons[] = new JButton[9];
private JButton exitButton;
public JLabel title;
public JPanel titlePanel, panel;
private int count = 0;
int symbolCount = 0;
private boolean win = false;
public TTT() {
title = new JLabel("Welcome to my Tic Tac Toe Game!");
titlePanel = new JPanel();
title.setFont(new Font(Font.SERIF, 0, 30));
titlePanel.add(title);
this.add(titlePanel, BorderLayout.NORTH);
panel = new JPanel(new GridLayout(3, 3));
for (int i = 0; i < buttons.length; i++) {
buttons[i] = new JButton();
panel.add(buttons[i]);
buttons[i].setEnabled(true);
buttons[i].addActionListener(this);
}
this.add(panel, BorderLayout.CENTER);
JPanel panel1 = new JPanel(new FlowLayout(FlowLayout.CENTER));
exitButton = new JButton("Quit");
panel1.add(exitButton);
this.add(panel1, BorderLayout.SOUTH);
exitButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.exit(WIDTH);
}
});
}
public void whoWins() {
//Determines who wins using for the horizontal rows.
if (buttons[0].getText() == buttons[1].getText() && buttons[1].getText() == buttons[2].getText() && buttons[0].getText() != "") {
win = true;
} else if (buttons[3].getText() == buttons[4].getText() && buttons[4].getText() == buttons[5].getText() && buttons[3].getText() != "") {
win = true;
} else if (buttons[6].getText() == buttons[7].getText() && buttons[7].getText() == buttons[8].getText() && buttons[6].getText() != "") {
win = true;
} //Determines the verticles wins
else if (buttons[0].getText() == buttons[3].getText() && buttons[3].getText() == buttons[6].getText() && buttons[0].getText() != "") {
win = true;
} else if (buttons[1].getText() == buttons[4].getText() && buttons[4].getText() == buttons[7].getText() && buttons[1].getText() != "") {
win = true;
} else if (buttons[2].getText() == buttons[5].getText() && buttons[5].getText() == buttons[8].getText() && buttons[2].getText() != "") {
win = true;
}
// Diagnol Wins
else if (buttons[0].getText()==buttons[4].getText()&&buttons[4].getText()==buttons[8].getText()&& buttons[0].getText()!= "") {
win = true;
}else if (buttons[2].getText()==buttons[4].getText()&&buttons[4].getText()==buttons[6].getText()&& buttons[1].getText()!= "") {
win = true;
}else {
win = false;
}
//who won
if (win = true) {
JOptionPane.showMessageDialog(null, "wins");
}else if (count == 9 && win == false) {
JOptionPane.showMessageDialog(null, "Tie game");
}
}
public static void main(String[] args) {
TTT ref1 = new TTT();
ref1.setTitle("Tic Tac Toe");
ref1.setVisible(true);
ref1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ref1.setSize(500, 500);
ref1.setLocationRelativeTo(null);
// ref1.whoWins();
}
#Override
public void actionPerformed(ActionEvent e) {
count++;
for (JButton button : buttons) {
if (button == e.getSource()) {
if (symbolCount % 2 == 0) {
button.setText("X");
button.setEnabled(false);
} else {
button.setText("O");
button.setEnabled(false);
}
}
}
if (count >= buttons.length) {
JOptionPane.showMessageDialog(null, "End");
}
symbolCount++;
}
}
If you really want to do this right, then I suggest making some big changes, some M-V-C type changes:
First and foremost, separate out the logic of the game from the game GUI. This would mean that the code that determines who wins should not be in any code that contains GUI type code. This will be your "model"
Next you should never have GUI code implement listener interfaces, so try to get that out of the GUI and possibly have it go into its own class, the "Control" class.
Finally the GUI or "View" class will concern itself with displaying the model's state and getting input from the user and transmitting this input to the control.
For example,...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.EnumMap;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;
public class TicTacToeMain {
private static void createAndShowGui() {
TttView view = null;
try {
view = new TttView();
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
TttModel model = new TttModel();
new TttControl(model, view);
JFrame frame = new JFrame("Tic Tac Toe");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(view.getMainPanel());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
enum TttPiece {
EMPTY, X, O
}
class TttView {
public static final String IMAGE = "/imgFolder/TicTacToe.png";
private static final int GAP = 5;
private JPanel mainPanel = new JPanel();
private JPanel tttPanel = new JPanel();
private Map<TttPiece, Icon> iconMap = new EnumMap<>(TttPiece.class);
private JLabel[][] grid = new JLabel[TttModel.ROWS][TttModel.COLS];
private TttControl control;
public TttView() throws IOException {
BufferedImage img = ImageIO.read(getClass().getResourceAsStream(IMAGE));
Icon[] imgIcons = splitImg(img);
iconMap.put(TttPiece.X, imgIcons[0]);
iconMap.put(TttPiece.O, imgIcons[1]);
iconMap.put(TttPiece.EMPTY, createEmptyIcon(imgIcons[0]));
tttPanel.setLayout(new GridLayout(grid.length, grid[0].length, GAP, GAP));
tttPanel.setBackground(Color.black);
MyMouseAdapter mouseAdapter = new MyMouseAdapter();
for (int row = 0; row < grid.length; row++) {
for (int col = 0; col < grid[row].length; col++) {
grid[row][col] = new JLabel(iconMap.get(TttPiece.EMPTY));
grid[row][col].setOpaque(true);
grid[row][col].setBackground(Color.LIGHT_GRAY);
grid[row][col].addMouseListener(mouseAdapter);
tttPanel.add(grid[row][col]);
}
}
JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 0));
btnPanel.add(new JButton(new ClearAction("Clear", KeyEvent.VK_C)));
btnPanel.add(new JButton(new ExitAction("Exit", KeyEvent.VK_X)));
int blGap = 2;
mainPanel.setLayout(new BorderLayout(blGap, blGap));
mainPanel.setBorder(BorderFactory.createEmptyBorder(blGap, blGap, blGap,
blGap));
mainPanel.add(tttPanel, BorderLayout.CENTER);
mainPanel.add(btnPanel, BorderLayout.SOUTH);
}
public void setControl(TttControl control) {
this.control = control;
}
public JComponent getMainPanel() {
return mainPanel;
}
private Icon createEmptyIcon(Icon icon) {
int width = icon.getIconWidth();
int height = icon.getIconHeight();
BufferedImage img = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB);
return new ImageIcon(img);
}
private Icon[] splitImg(BufferedImage img) {
int w = img.getWidth();
int h = img.getHeight();
int gap = 5;
Icon[] icons = new ImageIcon[2];
icons[0] = new ImageIcon(img.getSubimage(0, 0, w / 2 - gap, h / 2 - gap));
icons[1] = new ImageIcon(img.getSubimage(w / 2 + gap, 0, w / 2 - gap, h
/ 2 - gap));
return icons;
}
private class MyMouseAdapter extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
if (control == null) {
return;
}
for (int row = 0; row < grid.length; row++) {
for (int col = 0; col < grid[row].length; col++) {
if (grid[row][col] == e.getSource()) {
control.gridPress(row, col);
}
}
}
}
}
private class ClearAction extends AbstractAction {
public ClearAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent evt) {
if (control != null) {
control.clear();
}
}
}
private class ExitAction extends AbstractAction {
public ExitAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent evt) {
if (control != null) {
control.exit(evt);
}
}
}
public void setGridIcon(int row, int col, TttPiece tttPiece) {
grid[row][col].setIcon(iconMap.get(tttPiece));
}
}
class TttControl {
private TttModel model;
private TttView view;
public TttControl(TttModel model, TttView view) {
this.model = model;
this.view = view;
view.setControl(this);
model.addPropertyChangeListener(new ModelListener());
}
public void exit(ActionEvent evt) {
Window win = SwingUtilities
.getWindowAncestor((Component) evt.getSource());
win.dispose();
}
public void gridPress(int row, int col) {
try {
model.gridPress(row, col);
} catch (TttException e) {
// TODO: notify user
// e.printStackTrace();
}
}
public void clear() {
model.clear();
}
private class ModelListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (TttModel.GRID_POSITION.equals(evt.getPropertyName())) {
TttPiece[][] tttGrid = model.getTttGrid();
for (int row = 0; row < tttGrid.length; row++) {
for (int col = 0; col < tttGrid[row].length; col++) {
view.setGridIcon(row, col, tttGrid[row][col]);
}
}
}
}
}
}
class TttModel {
public static final int ROWS = 3;
public static final int COLS = ROWS;
public static final String GRID_POSITION = "grid position";
private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(
this);
private TttPiece[][] tttGrid = new TttPiece[ROWS][COLS];
private TttPiece player = TttPiece.X;
private boolean gameOver;
public TttModel() {
clear();
}
public void setGridPosition(int row, int col, TttPiece piece)
throws TttException {
if (gameOver) {
return;
}
if (tttGrid[row][col] == TttPiece.EMPTY) {
tttGrid[row][col] = piece;
checkForWin(row, col, piece);
nextPlayer();
pcSupport.firePropertyChange(GRID_POSITION, null, tttGrid);
} else {
String message = "Invalid setGridPosition for row: %d, col: %d, piece: %s. "
+ "Spot already occupied by piece: %s";
message = String.format(message, row, col, piece, tttGrid[row][col]);
throw new TttException(message);
}
}
public TttPiece[][] getTttGrid() {
return tttGrid;
}
public void gridPress(int row, int col) throws TttException {
setGridPosition(row, col, player);
}
public void nextPlayer() {
player = player == TttPiece.X ? TttPiece.O : TttPiece.X;
}
private void checkForWin(int row, int col, TttPiece piece) {
// TODO finish
}
public void clear() {
for (int row = 0; row < tttGrid.length; row++) {
for (int col = 0; col < tttGrid[row].length; col++) {
tttGrid[row][col] = TttPiece.EMPTY;
}
}
player = TttPiece.X;
pcSupport.firePropertyChange(GRID_POSITION, null, tttGrid);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(listener);
}
}
#SuppressWarnings("serial")
class TttException extends Exception {
public TttException() {
super();
}
public TttException(String message) {
super(message);
}
}
Using for my images:
With GUI looking like:
I am also interested in writing a Tic Tac Toe game, so I copied your code, and did a little modification, and it passed test, check following:
package eric.j2se.swing;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;
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.JOptionPane;
import javax.swing.JPanel;
/**
* <p>
* Simple game of Tic Tac Toe.
* </p>
*
* #author eric
* #date Apr 16, 2014 11:03:48 AM
*/
#SuppressWarnings("serial")
public class TicTacToe extends JFrame implements ActionListener {
// 2 players
public static final char playerX = 'X';
public static final char playerO = 'O';
// null player
public static final char playerN = 'N';
// the winer, init to null player
private Character winner = playerN;
// indicate whether game over
private boolean gameOver = false;
// count of button used,
private int count = 0;
private Character buttonPlayers[] = new Character[9];
private JButton buttons[] = new JButton[9];
private JButton exitButton;
public JLabel title;
public JPanel titlePanel, panel;
public TicTacToe() {
// init buttonPlayers
for (int i = 0; i < 9; i++) {
buttonPlayers[i] = playerN;
}
// init title
title = new JLabel("Welcome to Tic Tac Toe!");
titlePanel = new JPanel();
title.setFont(new Font(Font.SERIF, 0, 30));
titlePanel.add(title);
this.add(titlePanel, BorderLayout.NORTH);
// init 9 button
panel = new JPanel(new GridLayout(3, 3));
for (int i = 0; i < buttons.length; i++) {
buttons[i] = new JButton();
panel.add(buttons[i]);
buttons[i].setEnabled(true);
buttons[i].addActionListener(this);
}
// init exit button
this.add(panel, BorderLayout.CENTER);
JPanel panel1 = new JPanel(new FlowLayout(FlowLayout.CENTER));
exitButton = new JButton("Quit");
panel1.add(exitButton);
this.add(panel1, BorderLayout.SOUTH);
exitButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.exit(WIDTH);
}
});
}
public void whoWins() {
// determine winner - horizontal rows
if (!gameOver) {
for (int i = 0; i < 3; i++) {
if ((buttonPlayers[0 + i * 3] != playerN) && (buttonPlayers[0 + i * 3].equals(buttonPlayers[1 + i * 3]))
&& buttonPlayers[1 + i * 3].equals(buttonPlayers[2 + i * 3])) {
winner = buttonPlayers[0 + i * 3];
gameOver = true;
break;
}
}
}
// determine winner - vertical rows
if (!gameOver) {
for (int i = 0; i < 3; i++) {
if ((buttonPlayers[i + 0 * 3] != playerN) && (buttonPlayers[i + 0 * 3].equals(buttonPlayers[i + 1 * 3]))
&& buttonPlayers[i + 1 * 3].equals(buttonPlayers[i + 2 * 3])) {
winner = buttonPlayers[i + 0 * 3];
gameOver = true;
break;
}
}
}
// determine winner - diagonal rows
if (!gameOver) {
int winButtonIndex = -1;
if ((buttonPlayers[0] != playerN) && (buttonPlayers[0].equals(buttonPlayers[4])) && buttonPlayers[4].equals(buttonPlayers[8])) {
winButtonIndex = 0;
} else if ((buttonPlayers[2] != playerN) && (buttonPlayers[2].equals(buttonPlayers[4])) && buttonPlayers[4].equals(buttonPlayers[6])) {
winButtonIndex = 2;
}
if (winButtonIndex >= 0) {
winner = buttonPlayers[winButtonIndex];
gameOver = true;
}
}
// full
if (count == 9) {
gameOver = true;
}
if (gameOver) {
String tip = "";
switch (winner) {
case playerO:
tip = "Player O win!";
break;
case playerX:
tip = "Player X win!";
break;
default:
tip = "Draw game!";
break;
}
JOptionPane.showMessageDialog(null, tip);
}
}
#Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < buttons.length; i++) {
JButton button = buttons[i];
if (button == e.getSource()) {
Character currentPlayer = (count % 2 == 1 ? playerX : playerO);
button.setText(String.valueOf(currentPlayer));
buttonPlayers[i] = currentPlayer;
button.setEnabled(false);
break;
}
}
count++;
whoWins();
}
public static void main(String[] args) {
TicTacToe ref1 = new TicTacToe();
ref1.setTitle("Tic Tac Toe");
ref1.setVisible(true);
ref1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ref1.setSize(500, 500);
ref1.setLocationRelativeTo(null);
}
}
about when to call the win check:
check each time you click 1 of the 9 buttons,
about the flag:
I use 2 flag instead of 1 flag to indicate game over & winner, because in TTT game, draw game is very usual, after play several times, you always get draw game ...
a little suggestion to your code:
when compare string, use equals(), not ==,
define const values in variable, not write it in logic, e.g. 'O' 'X',
don't repeat code, try use logic control to make it short & easy to read & easy to maintain,
I have a problem.
I have an element that would JPanel.
In this JPanel would be four JButtons and image.
This image is 'green LED lights' that would change depending on which JButton would be pressed.
It works very well.
But also I want the JComboBox to change this paramter.
And here's the problem.
Although the parameter (from 1 to 4) is changing,(this shows JLabel near LEDs),
but the picture (LED lights) do not want to change it to the right one.
screenshot
The program is divided into 3 classes.
MyFrame.class This main class.
public class MyFrame extends JFrame {
int ctrlTriggers = 1;
private JLabel label = new JLabel();
private Triggers triggers;
private String[] typeTrig = {"1", "2", "3", "4"};
public MyFrame() {
JFrame frame = new JFrame("JComboBox Problem");
frame.setBounds(50, 0, 800, 240);
frame.setLayout(new BorderLayout());
int tvalue = 1;
String tstr = Integer.toString(tvalue);
JPanel panelTrig = new JPanel(new BorderLayout());
label = new JLabel(tstr, 4);
panelTrig.add(label);
final JLabel et = label;
triggers = new Triggers(typeTrig, "trigger " + Integer.toString(1));
triggers.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
Triggers tr = (Triggers) e.getSource();
int vol;
vol = (int) tr.getValue();
et.setText(Integer.toString(vol));
}
});
panelTrig.add(triggers, BorderLayout.LINE_START);
// JCOMBOBOX
JPanel pCombo = new JPanel();
pCombo.setLayout(new FlowLayout());
Presets combo = new Presets();
combo.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
Presets presetcombo = (Presets) e.getSource();
int tval;
tval = (int) presetcombo.getValue(ctrlTriggers);
label.setText(Integer.toString(tval));
triggers.setValue(tval);
}
});
pCombo.add(combo, BorderLayout.CENTER);
frame.add(pCombo, BorderLayout.CENTER);
frame.add(panelTrig, BorderLayout.LINE_START);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
frame.show();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new MyFrame();
}
});
}
}
Triggers.class This class is JPanel where is 4 JButton and 'LED like image'
public class Triggers extends JPanel
implements ActionListener, ItemListener {
public Triggers(String s[], String name) {
JPanel panel = new JPanel(new BorderLayout());
this.value = Integer.parseInt(s[selected]);
for (int i = 0; i < s.length; i++) {
ImageIcon cup = new ImageIcon();
button[i] = new JButton(z[i], cup);
button[i].setPreferredSize(new Dimension(70, 25));
Font font = button[i].getFont();
button[i].setFont(new Font(font.getFontName(), font.getStyle(), 10));
button[i].setActionCommand(s[i]);
if (i == selected) {
button[i].setSelected(true);
} else {
button[i].setSelected(false);
}
}
ButtonGroup group = new ButtonGroup();
for (int i = 0; i < s.length; i++) {
group.add(button[i]);
button[i].addActionListener(this);
button[i].addItemListener(this);
}
diody = new JLabel(createImageIcon("/resources/diody/"
+ this.value
+ ".png"));
diody.setPreferredSize(new Dimension(20, 100));
JPanel triggs = new JPanel(new FlowLayout());
triggs.setPreferredSize(new Dimension(80, 120));
for (int i = 0; i < s.length; i++) {
triggs.add(button[i]);
}
panel.add(triggs, BorderLayout.LINE_START);
panel.add(diody, BorderLayout.LINE_END);
add(panel);
}
public void actionPerformed(ActionEvent e) {
cmd = e.getActionCommand();
diody.setIcon(createImageIcon("/resources/diody/"
+ cmd
+ ".png"));
if (cmd.equals("1")) {
setValue(1);
} else if (cmd.equals("2")) {
setValue(2);
} else if (cmd.equals("3")) {
setValue(3);
} else if (cmd.equals("4")) {
setValue(4);
}
}
public static ImageIcon createImageIcon(String path) {
java.net.URL imgURL = Triggers.class.getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
public int setController() {
return value;
}
public void setValue(int k) {
this.value = k;
cmd = Integer.toString(this.value);
repaint();
fireChangeEvent();
}
public int getValue() {
return this.value;
}
public void setSel(int k) {
selected = k;
repaint();
fireChangeEvent();
}
public void itemStateChanged(ItemEvent ie) {
String s = (String) ie.getItem();
}
public void addChangeListener(ChangeListener cl) {
listenerList.add(ChangeListener.class, cl);
}
public void removeChangeListener(ChangeListener cl) {
listenerList.remove(ChangeListener.class, cl);
}
protected void fireChangeEvent() {
Object[] listeners = listenerList.getListenerList();
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == ChangeListener.class) {
if (changeEvent == null) {
changeEvent = new ChangeEvent(this);
}
((ChangeListener) listeners[i + 1]).stateChanged(changeEvent);
}
}
}
private ChangeEvent changeEvent = null;
private EventListenerList listenerList = new EventListenerList();
private JLabel diody;
private int x = 1;
private int y = 4;
private JButton button[] = new JButton[y];
double border = 4;
double vborder = 1;
int controller[] = new int[4];
String z[] = {"1", "2", "3", "4"};
private int selected;
private int value;
private String cmd;
}
class Presets Here is JCombobox.
public class Presets extends JPanel
implements ActionListener {
private int value;
private int[] ctrlIdx = new int[27];
private int controller;
private ChangeEvent changeEvent = null;
private EventListenerList listenerList = new EventListenerList();
private JLabel label;
private String[][] presets = {
{"0", "3"},
{"1", "2"},
{"2", "3"},
{"3", "1"},
{"4", "4"},
{"5", "2"},};
String[] ctrlName = {"preset 1 (value 3)", "preset 2 (value 2)", "preset 3 (value 3)", "preset 4 (value 1)", "preset 5 (value 4)", "preset 5 (value 2)"};
public Presets() {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.setPreferredSize(new Dimension(600, 30));
JComboBox combolist = new JComboBox(ctrlName);
combolist.setSelectedIndex(2);
combolist.addActionListener(this);
combolist.setPreferredSize(new Dimension(300, 30));
label = new JLabel();
label.setFont(label.getFont().deriveFont(Font.ITALIC));
label.setHorizontalAlignment(JLabel.CENTER);
int indeks = combolist.getSelectedIndex();
updateLabel(ctrlName[combolist.getSelectedIndex()], indeks);
label.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
label.setPreferredSize(new Dimension(300, 30));
panel.add(combolist, "East");
add(panel);
setPreferredSize(new Dimension(600, 40));
}
public void setSelectedItem(int a) {
}
public void setValue(int c, int v) {
controller = c;
value = v;
ctrlIdx[controller] = value;
repaint();
fireChangeEvent();
}
public int getController() {
return controller;
}
public int getValue(int c) {
int w = (int) ctrlIdx[c];
return (int) w;
}
public void actionPerformed(ActionEvent e) {
JComboBox cb = (JComboBox) e.getSource();
String pres = (String) cb.getSelectedItem();
int indeks = cb.getSelectedIndex();
updateLabel(pres, indeks);
for (int i = 0; i < ctrlName.length; i++) {
for (int j = 0; j < 2; j++) {
setValue(j, Integer.parseInt(presets[indeks][j]));
}
}
}
protected void updateLabel(String name, int ii) {
label.setToolTipText("A drawing of a " + name.toLowerCase());
}
protected static ImageIcon createImageIcon(String path) {
java.net.URL imgURL = Presets.class.getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
public void addChangeListener(ChangeListener cl) {
listenerList.add(ChangeListener.class, cl);
}
public void removeChangeListener(ChangeListener cl) {
listenerList.remove(ChangeListener.class, cl);
}
protected void fireChangeEvent() {
Object[] listeners = listenerList.getListenerList();
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == ChangeListener.class) {
if (changeEvent == null) {
changeEvent = new ChangeEvent(this);
}
((ChangeListener) listeners[i + 1]).stateChanged(changeEvent);
}
}
}
}
Could someone help me, what am I doing wrong?
Your image is only begin loaded in the actionPerformed method of your Triggers class, which means when you call setValue in response to the stateChanged event thrown by the Presets class, no new image is begin loaded.
Move your image loading logic so it is either in the setValue method or triggered by the setValue method
I am trying to add horizontal scroll bar in a JComboBox using reference with thread - Horizontal scrollbar for JComboBox across multiple look and feel at the OTN, but it's not working in my case.
How to add a horizontal scroll bar to JComboBox correctly?
Code -
public class TestJComboBoxWithScrollBar {
TestJComboBoxWithScrollBar() {
JDialog jDialog = new JDialog();
jDialog.setTitle("Test JComboBox With ScrollBar");
JPanel jPanel_Sort = new JPanel();
GridBagLayout gbl = new GridBagLayout();
GridBagConstraints bagConstraints = new GridBagConstraints();
jPanel_Sort.setLayout(gbl);
bagConstraints.gridwidth = 1;
bagConstraints.gridheight = 1;
bagConstraints.fill = GridBagConstraints.NONE;
bagConstraints.anchor = GridBagConstraints.WEST;
bagConstraints.weightx = 0;
bagConstraints.weighty = 0;
bagConstraints.insets = new Insets(5, 5, 5, 5);
bagConstraints.gridx = 0;
bagConstraints.gridy = 0;
SampleJComboBoxWithScrollBar cmbHeaders = new SampleJComboBoxWithScrollBar();
cmbHeaders.addItem("aaaaaaaaaaaaa");
cmbHeaders.addItem("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
cmbHeaders.setPreferredSize(new Dimension(190, 50));
cmbHeaders.setMinimumSize(new Dimension(190, 50));
cmbHeaders.setMaximumSize(new Dimension(190, 50));
jPanel_Sort.add(cmbHeaders, bagConstraints);
JCheckBox chkOrderBy = new JCheckBox("Asc");
bagConstraints.gridx = 1;
bagConstraints.gridy = 0;
jPanel_Sort.add(chkOrderBy, bagConstraints);
jPanel_Sort.setPreferredSize(new Dimension(220, 70));
jPanel_Sort.setMinimumSize(new Dimension(220, 70));
jPanel_Sort.setMaximumSize(new Dimension(220, 70));
jDialog.add(jPanel_Sort, BorderLayout.CENTER);
jDialog.setPreferredSize(new Dimension(300, 100));
jDialog.pack();
jDialog.setResizable(false);
jDialog.setModal(true);
jDialog.setVisible(true);
}
public static void main(String[] argu) {
new TestJComboBoxWithScrollBar();
}
class SampleJComboBoxWithScrollBar extends JComboBox {
SampleJComboBoxWithScrollBar() {
super();
this.addPopupMenuListener(this.getPopupMenuListener());
this.adjustScrollBar();
}
private void adjustPopupWidth() {
if (getItemCount() == 0) {
return;
}
Object comp = getUI().getAccessibleChild(this, 0);
if (!(comp instanceof JPopupMenu)) {
return;
}
JPopupMenu popup = (JPopupMenu) comp;
JScrollPane scrollPane = (JScrollPane) popup.getComponent(0);
Object value = getItemAt(0);
Component rendererComp = getRenderer().getListCellRendererComponent(new JList(), value, 0, false, false);
if (rendererComp instanceof JXTable) {
scrollPane.setColumnHeaderView(((JTable) rendererComp).getTableHeader());
}
Dimension prefSize = rendererComp.getPreferredSize();
Dimension size = scrollPane.getPreferredSize();
size.width = Math.max(size.width, prefSize.width);
scrollPane.setPreferredSize(size);
scrollPane.setMaximumSize(size);
scrollPane.revalidate();
}
private void adjustScrollBar() {
if (getItemCount() == 0) {
return;
}
Object comp = getUI().getAccessibleChild(this, 0);
if (!(comp instanceof JPopupMenu)) {
return;
}
JPopupMenu popup = (JPopupMenu) comp;
JScrollPane scrollPane = (JScrollPane) popup.getComponent(0);
scrollPane.setHorizontalScrollBar(new JScrollBar(JScrollBar.HORIZONTAL));
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
}
private PopupMenuListener getPopupMenuListener() {
return new PopupMenuListener() {
#Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
adjustPopupWidth();
}
#Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
}
#Override
public void popupMenuCanceled(PopupMenuEvent e) {
}
};
}
}
}
if you meaning code posted by #Kleopatra then void adjustScrollBar() never will be called from PopupMenuListener
private PopupMenuListener getPopupMenuListener() {
return new PopupMenuListener() {
#Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
//adjustPopupWidth();
adjustScrollBar();
}
#Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
}
#Override
public void popupMenuCanceled(PopupMenuEvent e) {
}
};
}