Can't switch between tabs having ToolTipText assigned (JTabbedPane) - java

I have a JFrame extended class that implements a multi-tab chat. Every tab is a chat with someone or with a group of people. What I have implemented works fine, except when I assign a ToolTipText to the label of a tab. In this case I can't click anymore (and select) the tab that has a ToolTipText assigned. The others work fine.
Graphical example:
As you can see the tabs are properly being added, and the first two tabs ("Gruppo prova" and "Gruppo test") have a ToolTipText, the other two don't. I can switch between the last two, but I can't do the same with the first two. I thought that the icon next to the label could be a problem, but I removed it and still doesn't work. However I can still click all the 'X' (close) buttons (working properly).
This is a piece of the code I used to add a tab:
// Some stuff...
JChat chat = new JChat(gui.chatClient, email, name, group);
jTabbedPane.add(email, chat); // I instantiated this before
int index = jTabbedPane.indexOfTab(email);
JPanel pnlTab = new JPanel(new GridBagLayout());
pnlTab.setOpaque(false);
// Core function
JLabel lblTitle;
if (group == 1) {
// If it's a group and not a single chat I assign a name, an icon and a ToolTipText to the tab
lblTitle = new JLabel(name, icon, JLabel.LEFT);
lblTitle.setToolTipText(membersList.toString());
} else {
// otherwise I only assign a name to the tab
lblTitle = new JLabel(name);
}
jTabbedPane.setTabComponentAt(index, pnlTab);
// This applies the 'X' (close) button next to the tab name
CloseButton btnClose = new CloseButton(this, jTabbedPane, tabs, email);
lblTitle.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
pnlTab.add(lblTitle);
pnlTab.add(btnClose);
Is this a Swing bug or am I doing something wrong?

you can use :
void setToolTipTextAt(int, String) to set tool-tip text to specific tab.
void setIconAt(int index, Icon icon) to set the icon to specific tab.
No need to use JLabel for setting tool-tip text or icon.
The above solution, however doesn't however answer your question:
except when I assign a ToolTipText to the label of a tab. In this
case I can't click anymore (and select) the tab that has a ToolTipText
assigned
The only reason i am suspecting:
JLabel doesn't register to any mouse listener by default. When no mouse listener is set to JLabel any mouse clicked event will go through to the UI objects underneath: in this case the JTabbedPane. But when we are setting tool-tip text using setToolTipText(text), the ToolTipManger adds a mouse listener to this JLabel, which will continue to consume the mouse click event.
Check the following code snippets demonstrating the issue and providing a work around setSelectedIndex function:
JLabel label = new JLabel("a Label");
System.out.println(label.getMouseListeners().length); // length is printed as 0
label.setToolTipText("Danger: setting tool tip will consume mouse event");
System.out.println(label.getMouseListeners().length); // length is printed as 1
jTabbedPane1.setTabComponentAt(0, label);
label.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
int index = jTabbedPane1.indexOfTabComponent((Component)e.getSource());
jTabbedPane1.setSelectedIndex(index);
}
});

Related

How to know in which JTextPane the cursor is?

I have several JtextPanes and I want to create a method that set the value of a variable to the name of the TextPane which has been clicked because another methond is going to use it. There's also a button that adds a new jTextPane when the user clicks on it and I want those new TextPanes to inherit that method. Or if you know a simpler way to achieve that I'm open to read you. Let me know if you need more information or more code.
static JTextPane focus;
private void redColorActionPerformed(java.awt.event.ActionEvent evt) { //Ths is the method that works with the focus variable. It changes the color of the text in the clicked textpane.
TextEditor.cambiarColor(new java.awt.Color(255, 0, 0), focus);
}
It sound like you want to know the current Swing JTextPane component under the current mouse position? Then try to
Get current Mouse position
Point position = MouseInfo.getPointerInfo().getLocation();
Get the component under the mouse location
Component c = SwingUtilities.getDeepestComponentAt(
the-root-component,
position.getX(),
position.getY()
);
if (c instanceof JTextPane) {
// do your logic
}

Grid layout not working?

I am trying to make a 2x2 grid layout that has a JLabel on the top left, and three buttons on the other three spaces. When I do this, I get the unexpected result of one big button (filling up the entire JDialog) that says "Do you want to push me". I don't know why this result shows up, please help, Thanks!
public void sinceyoupressedthecoolbutton() {
JDialog replacementwindow = new JDialog(); //Like a window
JButton best = new JButton("best");
JButton first = new JButton("FIRST");
JButton second = new JButton("Second");
replacementwindow.setLayout(new GridLayout(2,3,0,0)); //Row, column, distance horizontally, distance vertical
JPanel panel = new JPanel();
replacementwindow.add(panel); //adding the JPanel itself
replacementwindow.add(first);
replacementwindow.add(second);
replacementwindow.add(best);
replacementwindow.setSize(500, 500);
replacementwindow.setTitle("NEW WINDOW!");
replacementwindow.setVisible(true);
}
It's because you set the layout of your JButton, and not of your JDialog
Change
label.setLayout(new GridLayout(2,2,0,0));
to
YES.setLayout(new GridLayout(2,2,0,0));
Also, your variable called label is a JButton, you probably want to change that.
Don't add components to a button. You add components to a panel.
So the basic code should be:
JDialog dialog = new JDialog(...);
JPanel panel = new JPanel( new GridLayout(...) );
panel.add(label);
panel.add(button1);
...
dialog.add(panel);
Also, variable names should NOT start with an upper case character! "Yes" does not follow Java standards. The other variables do. Be consistent!

Checkerboard not showing? Section of application just black?

First off I would like to say that I understand I am asking a lot so any help would be appreciated and I thank you for your time. I am extremely grateful.
Anyway I am creating a game for my A2 coursework, most commonly known as Checkers. I have completed my code and everything works as I had planned except that the CheckerBoard itself as well as the checkerpieces do not appear to be showing.
The section of were my board should be present is just a black space. Although my board does not appear to be displaying, all of the actions I perform on it such as clicking certain section produces the planned response, and although I've checked through my code I cannot work out what I've done wrong.
Anyway if anyone could possibly spot my mistake or perhaps give me some advice I would be extremely grateful. Thank you
public class CheckerBoard extends JPanel implements ActionListener, MouseListener {
// Main routine that opens an Applet that shows a CheckerBoard
public static void main(String[] args) {
JFrame application = new JFrame("Checkers"); // Sets the title at the top of the application as 'Checkers'
JMenuBar bar = new JMenuBar(); // Adds the Menu Bar
JMenu fileMenu = new JMenu("File"); // Adds a File Tab to the Menu Bar
JMenu helpMenu = new JMenu("Help"); // Adds a Help Tab to the Menu Bar
JMenuItem exit = new JMenuItem("Exit"); // Adds the Exit sub-tab as an Item of the JMenu
JMenuItem mainMenu = new JMenuItem("Main Menu"); // Adds the Main Menu sub-tab as an Item of the JMenu
final JMenuItem Rules = new JMenuItem("Rules"); // Adds the Rules of Checkers sub-tab as an Item of the JMenu
helpMenu.add(Rules); // Adds the Rules of Checkers tab into the Help tab
fileMenu.add(mainMenu);// Adds the Main Menu sub-tab into the File tab
fileMenu.addSeparator(); // Adds a line in between the Main Menu sub-tab and the Exit sub-tab
fileMenu.add(exit); // Adds the Exit sub-tab into the Menu tab
bar.add(fileMenu); // Adds the Menu tab to the Menu bar
bar.add(helpMenu); // Adds the Help tab to the Menu Bar
application.setJMenuBar(bar); // Adds the Menu Bar to the application window
Rules.addActionListener(new ActionListener() // Adds a new ActionListener to the Rules sub-tab
{
public void actionPerformed(ActionEvent ev)
{
JOptionPane.showMessageDialog(Rules,
"- Pieces must always move diagonally\n" +
"- Single pieces are limited to forward moves\n" +
"- Kings may move both forward and backward\n" +
"- When a piece is captured, it is removed from the board\n" +
"- If a player is able to make a capture, there is no option, the jump must be made\n" +
"- When a piece reaches the opponents end of the board, it is crowned and becomes a King",
"Rules for Checkers",
JOptionPane.PLAIN_MESSAGE);
}
}); //This has added a JOptionPane action when my Rules sub-tab is clicked, this displays the message dialog of the JOptionPane which can be seen
exit.addActionListener(new ActionListener() // Adds an ActionListener to the Exit Sub-tab
{
public void actionPerformed(ActionEvent ev)
{
System.exit(0); // This means that when the Exit sub-tab is clicked, it will exit the application
}
});
CheckerBoard content = new CheckerBoard(); // Sets the CheckerBoard values into the content to be used in the next line
application.setContentPane(content); // Container holds the values together, Content pane of the CheckerBoard
application.pack(); // Use preferred size of content to set size of application.
Dimension screensize = Toolkit.getDefaultToolkit().getScreenSize();
application.setLocation( (screensize.width - application.getWidth())/2,
(screensize.height - application.getHeight())/2 );
application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); // Sets so that the application can be exited when the application is closed
application.setResizable(false); // This makes it so that the user can't change the application's size.
application.setVisible(true); // Sets it so that the application can actually be seen
}
private JButton NewGameButton; // Button for starting a new game.
private JButton ResignButton; // Button that a player can use to end the game by resigning
private JLabel MessageDisplay; // Label for displaying messages to the user.
public CheckerBoard() {
// This is going to be a constructor, this constructor will set the layout manager for the panel to be null, it will then add components to the panel
// and it will set their bounds.
setLayout(null); // So that it will match my requirement specification, I will do the layout myself
setBackground(new Color(0,120,0)); // Dark Green Background colour.
setPreferredSize(new Dimension(350,250)); // The size of the Panel
BoardComplete checkerboardData = new BoardComplete();
add(checkerboardData); // This will create the components and add them to the content pane
add(NewGameButton);
add(ResignButton);
add(MessageDisplay);
// I will now have to produce a method to set the position and size of each component by calling its setBounds() method
checkerboardData.setBounds(20,20,164,164); // Sets the board dimensions
NewGameButton.setBounds(210, 60, 120, 30);
ResignButton.setBounds(210, 120, 120, 30);
MessageDisplay.setBounds(20, 200, 350, 30);
}
public class BoardComplete extends JPanel implements ActionListener, MouseListener {
DataForCheckers checkerboardData; // This is where the data for the checkerboard is going to be kept, this board will be responsible for the
// generating of the lists of the legal moves then I will define at a later stage.
boolean CheckerMatchInProgress; // In some of the actions I will be creating, I will have to check whether a game is in progress
// therefore this is a boolean value as it is either true or false, only two possible outcomes.
// The next three variables as seen below will only be valid when the game is in progress
int ChosenRow, ChosenColumn; // If the current player has selected a piece to
// move, these give the row and column
// containing that piece. If no piece is
// yet selected, then ChosenRow is -1.
int ChosenPlayer; // This will check which user turn it is, there will be two possible values which will include DataForCheckers.RED and Checkers.Data.BLACK
DataForMoves[] LegalMoves; // An array containing the legal moves for the
// current player.
// The constructor will create the buttons and the labels. It will
// listen for mouse clicks and for clicks on the buttons. It will create
// the board and start the first game.
BoardComplete() {
setBackground(Color.BLACK);
addMouseListener(this);
ResignButton = new JButton("Resign");
ResignButton.addActionListener(this);
NewGameButton = new JButton("New Game");
NewGameButton.addActionListener(this);
MessageDisplay = new JLabel("",JLabel.CENTER);
MessageDisplay.setFont(new Font("Serif", Font.BOLD, 14));
MessageDisplay.setForeground(Color.green);
checkerboardData = new DataForCheckers();
}
// Now I will have to draw the checkerboard pattern in Gray and LightGray
// Just like with my CheckerBoard Class, this will draw the checkers, and if
// a game is in progress, it will highlight the legal moves that the user can make.
public void PaintCheckerBoard(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// This will draw a two-pixel black border around the edges of the canvas.
g.setColor(Color.black);
g.drawRect(0,0,getSize().width-1,getSize().height-1);
g.drawRect(1,1,getSize().width-3,getSize().height-3);
// Draw the squares of the checkerboard and the checkers.
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
if ( row % 2 == col % 2 )
g.setColor(Color.LIGHT_GRAY);
else
g.setColor(Color.GRAY);
g.fillRect(2 + col*20, 2 + row*20, 20, 20);
switch (checkerboardData.PieceLocation(row,col)) {
case DataForCheckers.RED:
g.setColor(Color.RED);
g.fillOval(4 + col*20, 4 + row*20, 15, 15);
break;
case DataForCheckers.BLACK:
g.setColor(Color.BLACK);
g.fillOval(4 + col*20, 4 + row*20, 15, 15);
break;
case DataForCheckers.RED_KING:
g.setColor(Color.RED);
g.fillOval(4 + col*20, 4 + row*20, 15, 15);
g.setColor(Color.WHITE);
g.drawString("K", 7 + col*20, 16 + row*20);
break;
case DataForCheckers.BLACK_KING:
g.setColor(Color.BLACK);
g.fillOval(4 + col*20, 4 + row*20, 15, 15);
g.setColor(Color.WHITE);
g.drawString("K", 7 + col*20, 16 + row*20);
break;
}
}
}
} // end PaintCheckerBoard()
I understand that this is a lot to ask but any help would be greatly appreciate and I would be extremely grateful. Thank you so much
Basically, nothing calls your PaintCheckerBoard method.
Check Painting in AWT and Swing and Performing Custom Painting for more details about how painting works in Swing.
Essentially, you need to override the BoardComplete's paintComponent and perform you custom painting from within it
Having said that, it would probably be easier to achieve with a GridLayout
Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify

Java: JCheckBox won't stay checked with ItemListener

Ok, I'm new to listeners (still learning the language), and this is my first full-scale attempt to implement them (ie more than just a practice problem in a textbook).
So far, everything is working fine except one big bug: the checkboxes don't stay checked. The ItemListener I assign them runs perfectly (I have a JOptionPane set up to trigger to let me know if it's working or not), but the box itself doesn't stay checked.
I went even further and added conditional logic for if it's state is checked versus unchecked, and found that when I click the box BOTH states get triggered. So I get both JOptionPane popups, the one with the message for if the box is checked and the one for if the box isn't checked.
I'm including my code here. What am I doing wrong?
PS. You'll notice that the code has conditional logic to either add a radio button or a checkbox. When the program finally runs, this component is generated in multiple locations in both formats. The radio button works fine, it's the checkbox ones that I'm having the above issue with.
CODE THAT CREATES THE CHECKBOXES AND ASSIGNS THE LISTENERS:
public OtherField(int voteFor){
this.voteFor = voteFor;
otherPanel = new JPanel();
otherPanel.setLayout(new GridLayout(1, 3));
otherField = new JTextField(10);
otherField.setHorizontalAlignment(SwingConstants.CENTER);
JLabel otherLabel;
otherLabel = new JLabel("Other", SwingConstants.CENTER);
otherRadio = new JRadioButton("", false);
otherRadio.setHorizontalAlignment(SwingConstants.CENTER);
otherRadio.addActionListener(new OtherFieldRadioListener());
otherCheckBox = new JCheckBox("");
otherCheckBox.setHorizontalAlignment(SwingConstants.CENTER);
otherCheckBox.addItemListener(new OtherFieldCheckBoxListener());
otherPanel.add(otherLabel);
otherPanel.add(otherField);
if(voteFor == 1){
otherPanel.add(otherRadio);
}else{
otherPanel.add(otherCheckBox);
}
}
LISTENER CODE (it's a private class in the same class as the code above):
private class OtherFieldCheckBoxListener implements ItemListener{
public void itemStateChanged(ItemEvent e){
String name = otherField.getText();
if(e.getStateChange() == ItemEvent.SELECTED){
JOptionPane.showMessageDialog(null, name);
}else{
JOptionPane.showMessageDialog(null, "Not Selected");
}
}
}
First thing I would try is to set the checkbox either to true or false when you initialize it, i.e
otherCheckBox.setSelected(false)
If this does not work I would check whether OtherField gets called from somewhere else everytime the checkbox is selected and thus the components are redrawn/ the selection is reset (use the debugger and set a breakpoint at the beginning of OtherFields)

Add popup JTextarea to each column title in JTable

I am trying to make a JTable with popup help menus for each column section. For instance, you right click on the first column title and a JTextArea pops up that explains what the column is for and what type of data should be put into it. I have the following code establishing the JTable and the mouselistener event. Is there a way I can write an If statement using ColumnAtPoint() so that if the right click happens at Column 1, then it opens up my JTextArea? Then I can create a second and third separate JTextAreas for my other columns.
final DefaultTableModel tblModel = new DefaultTableModel(null, colHdrs);
final JTable table = new JTable(tblModel);
table.getTableHeader().addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e))
{
JOptionPane.showMessageDialog(null, textArea1, "Type", JOptionPane.PLAIN_MESSAGE);
}
}
});
Try to use JToolTip I think it might be much more suited for your use ;) :)!
You can also add e.g. to a
JLabel label = new JLabel("My Number Label");
a tooltip text like :
label.setToolTipText("Only Numbers From 1-10 are allowed!");
This is also possible for other swing stuff, you can try it :).
The text will appear as soon as you hover over the label .

Categories