I'm attempting to change the color of the border of a JTabbedPane based on the selected tab. Using answers here and on the web, I've managed this:
import java.awt.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.basic.BasicTabbedPaneUI;
public class TabbedPaneTest implements Runnable {
JTabbedPane pane = new JTabbedPane();;
public void run() {
// magenta border first so any changes will be obvious
setTabbedPaneBorderColor(new Color(255, 0, 255));
JPanel container = new JPanel();
container.setSize(new Dimension(500, 200));
pane.setPreferredSize(new Dimension(400, 200));
pane.addTab("A", createTab(Color.RED));
pane.addTab("B", createTab(Color.YELLOW));
pane.addTab("C", createTab(Color.BLUE));
pane.addChangeListener(new TabSelected());
container.add(pane);
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(container);
frame.setSize(500, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JPanel createTab(Color color) {
JPanel p = new JPanel();
p.setBorder(BorderFactory.createLineBorder(color, 2));
return p;
}
private class TabSelected implements ChangeListener {
#Override
public void stateChanged(ChangeEvent e) {
int index = pane.getSelectedIndex();
switch (index) {
case 0:
setTabbedPaneBorderColor(Color.RED);
break;
case 1:
setTabbedPaneBorderColor(Color.YELLOW);
break;
case 2:
setTabbedPaneBorderColor(Color.BLUE);
break;
}
}
}
public void setTabbedPaneBorderColor(Color tabBorderColor) {
UIManager.put("TabbedPane.borderHightlightColor", tabBorderColor);
UIManager.put("TabbedPane.darkShadow", tabBorderColor);
UIManager.put("TabbedPane.shadow", tabBorderColor);
UIManager.put("TabbedPane.light", tabBorderColor);
UIManager.put("TabbedPane.highlight", tabBorderColor);
UIManager.put("TabbedPane.focus", tabBorderColor);
UIManager.put("TabbedPane.selectHighlight", tabBorderColor);
pane.setUI(new BasicTabbedPaneUI() {
#Override
protected void installDefaults() {
super.installDefaults();
highlight = UIManager.getColor("TabbedPane.light");
lightHighlight = UIManager.getColor("TabbedPane.highlight");
shadow = UIManager.getColor("TabbedPane.shadow");
darkShadow =UIManager.getColor("TabbedPane.darkShadow");
focus = UIManager.getColor("TabbedPane.focus");
}
});
}
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(new TabbedPaneTest());
}
}
In particular, the setTabbedPaneBorderColor() method does exactly what I wanted (that is, it modifies the fancy border around the tabs, rather than the border on the panels contained in it or a plain rectangular border around the entire space the JTabbedPane occupies). For some reason this example throws an error that doesn't show up in my actual program (I think it's related to the SwingWorker and EDT). Now I'm trying to figure out how to change the selected tab's background.
The relevant property is
UIManager.put("TabbedPane.selected",Color.MAGENTA);
However, I don't seem to have a way to use that in the tabUI (it's baffling, but there's no background Color variable in BasicTabbedPaneUI).
Edit: Hopefully someone more knowledgeable will come by with a good answer, but if you googled this my current solution is to use a neutral color for the selected tab's background color since there seems to be no simple way to update it. I also switched to a neutral tab border (even though you CAN update that as the example shows) and created the colored borders inside the contained JPanels. It's not ideal, but it looks pretty good and I don't have time to continue looking for a cleaner solution at the moment.
This is worked for me
UIManager.getLookAndFeelDefaults().put("TabbedPane:TabbedPaneTab[Enabled].backgroundPainter", new BackgroundPainter(Color.white));
UIManager.getLookAndFeelDefaults().put("TabbedPane:TabbedPaneTab[Enabled+MouseOver].backgroundPainter", new BackgroundPainter(Color.white));
UIManager.getLookAndFeelDefaults().put("TabbedPane:TabbedPaneTab[Enabled+Pressed].backgroundPainter", new BackgroundPainter(Color.white));
UIManager.getLookAndFeelDefaults().put("TabbedPane:TabbedPaneTab[Focused+MouseOver+Selected].backgroundPainter", new BackgroundPainter(Color.white));
UIManager.getLookAndFeelDefaults().put("TabbedPane:TabbedPaneTab[Focused+Pressed+Selected].backgroundPainter", new BackgroundPainter(Color.white));
UIManager.getLookAndFeelDefaults().put("TabbedPane:TabbedPaneTab[Focused+Selected].backgroundPainter", new BackgroundPainter(Color.GRAY));
UIManager.getLookAndFeelDefaults().put("TabbedPane:TabbedPaneTab[MouseOver+Selected].backgroundPainter", new BackgroundPainter(Color.white));
UIManager.getLookAndFeelDefaults().put("TabbedPane:TabbedPaneTab[Pressed+Selected].backgroundPainter", new BackgroundPainter(Color.white));
UIManager.getLookAndFeelDefaults().put("TabbedPane:TabbedPaneTab[Selected].backgroundPainter", new BackgroundPainter(Color.white));
BackgroundPainter class
public class BackgroundPainter implements Painter<JComponent> {
private Color color = null;
BackgroundPainter(Color c) {
color = c;
}
#Override
public void paint(Graphics2D g, JComponent object, int width, int height) {
if (color != null) {
g.setColor(color);
g.fillRect(0, 0, width - 1, height - 1);
}
}
}
for me, it worked, I just set the UImanager's TabbedPane.selected color property before creation of JTabbedPane object.
UIManager.put("TabbedPane.selected", Color.red);
tabbedPane = new JTabbedPane();
Refer this link, i'm sure it will work for you too.
http://esus.com/changing-the-color-of-the-selected-tab-of-a-jtabbedpane/
Related
public class Main {
public static class GUI extends JFrame {
public GUI() {
//Title
super("Draw Card");
//panel
Panel buttonsPanel = new Panel();
Panel imagePanel = new Panel();
//App layout
setSize(600,480);
setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
//gc value
gc.gridy=0;gc.gridx=0;gc.gridwidth=1;gc.gridheight=1;gc.weightx=0.5;gc.weighty=0;gc.fill = GridBagConstraints.HORIZONTAL;
//layout in layout
GridLayout buttonsLayout = new GridLayout(1,2);
GridLayout imageLayout = new GridLayout(4,13);
buttonsPanel.setLayout(buttonsLayout);
imagePanel.setLayout(imageLayout);
//add
add(buttonsPanel,gc);
//change gc value
gc.gridy=1;gc.weighty=1;gc.gridheight=9;gc.fill = GridBagConstraints.BOTH;
//add
add(imagePanel,gc);
//button
JButton btn = new JButton("Draw card");
buttonsPanel.add(btn);
buttonsPanel.add(new JButton("Remove cards."));
//event
btn.addActionListener(e ->{
//just image from link
Image image = null;
try {
URL url = new URL("https://www.improvemagic.com/wp-content/uploads/2020/11/kj.png");
image = ImageIO.read(url);
} catch (IOException ee) {
ee.printStackTrace();
}
//add to label then add label to panel
JLabel label = new JLabel(new ImageIcon(image));
imagePanel.add(label);
revalidate();
});
//set visible
setVisible(true);
}
}
public static void main(String[] args){
GUI test = new GUI();
}
}
EDITED: I dont think i can make it shorter without destroying everything, only one image and it's online, got the same problem that i have.
I've tryed a couple a thing on the pannel and the layout to give the image size for each cell but didnt worked.
Hello ! I have some trouble to keep the full image, i didn't find a single way of getting them fully, did I miss something about those layout ?
I'm still not used to post here ask me if i need to add things ! Thank you !
I have a baglayout that contain 2 gridlayout (one for button and another one where I want to add random card by clicking on one button)
Introduction
I reworked your code to create the following GUI.
Here's the same GUI after drawing a few cards.
The JFrame worked out to be 822 x 420 pixels. In Swing, you work from the inside out. You create Swing components, put the Swing components in JPanels, put the JPanels in a JFrame, and see what the size of the JFrame turns out to be.
Explanation
Whenever I create a Swing GUI, I use the model/view/controller (MVC) pattern. This pattern implies that you create the model first, then the view, then the controller. For complex projects, the process is more iterative than waterfall.
The MVC pattern in Swing development means:
The view reads information from the model.
The view does not modify the model.
The controller modifies the model and updates the view.
There's usually not one controller class "to rule them all". Each Action or ActionListener class is responsible for its portion of the model and the view.
Model
I assumed you eventually wanted to read more than one card image, so I created a Card class. This class holds the card Image and whatever information you want about a playing card, including descriptive text, suit, int value, and int suit value.
I created a SomeCardGameModel class to hold a blank card, a card, and an int cardCount. The cardCount helps ensure that we don't draw more than 52 cards.
Reducing the size of the card image turned out to be a bit of a challenge. I used a search engine to find relevant bits of code and put them together in the SomeCardGameModel class. The main point is that you do all of the model creation before you create the view.
View
I started the Swing application with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components will be created and executed on the Event Dispatch Thread.
I separated the creation of the JFrame and the JPanels into separate methods. This makes the code much easier for people to understand what you're doing.
The JFrame has a default BorderLayout. I used a BorderLayout for the main JPanel and GridLayouts for the button JPanel and the card JPanel. I added some spacing between the Swing components so you can see individual cards.
Controller
After creating a model and a view, your anonymous controller class is simplified. You should be able to create the controller for the "remove Cards" JButton.
Code
Here's the complete runnable code. I made all the additional classes inner classes so I can post this code as one block.
import java.awt.BorderLayout;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class SomeCardGame implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new SomeCardGame());
}
private JLabel[] cardLabels;
private final SomeCardGameModel model;
public SomeCardGame() {
this.model = new SomeCardGameModel();
}
#Override
public void run() {
JFrame frame = new JFrame("Draw Card");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
System.out.println(frame.getSize());
}
public JPanel createMainPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
panel.add(createButtonPanel(), BorderLayout.NORTH);
panel.add(createCardPanel(), BorderLayout.CENTER);
return panel;
}
public JPanel createButtonPanel() {
JPanel panel = new JPanel(new GridLayout(0, 2, 5, 5));
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JButton drawButton = new JButton("Draw card");
panel.add(drawButton);
drawButton.addActionListener(e -> {
int count = model.getCardCount();
if (count < 52) {
cardLabels[model.getCardCount()].setIcon(
new ImageIcon(model.getCard().getCardImage()));
model.incrementCardCount(1);
}
});
JButton removeButton = new JButton("Remove cards");
panel.add(removeButton);
return panel;
}
public JPanel createCardPanel() {
JPanel panel = new JPanel(new GridLayout(0, 13, 5, 5));
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
this.cardLabels = new JLabel[52];
for (int index = 0; index < cardLabels.length; index++) {
cardLabels[index] = new JLabel(new ImageIcon(
model.getBlankCard().getCardImage()));
panel.add(cardLabels[index]);
}
return panel;
}
public class SomeCardGameModel {
private int cardCount;
private final Card blankCard;
private final Card card;
public SomeCardGameModel() {
this.blankCard = new Card(createBlankCard());
BufferedImage image = readCard();
Image reducedImage = image.getScaledInstance(
56, 78, Image.SCALE_SMOOTH);
this.card = new Card(toBufferedImage(reducedImage));
this.cardCount = 0;
}
private BufferedImage createBlankCard() {
BufferedImage image = new BufferedImage(56, 78,
BufferedImage.TYPE_INT_RGB);
return image;
}
private BufferedImage readCard() {
try {
URL url = new URL("https://www.improvemagic.com/"
+ "wp-content/uploads/2020/11/kj.png");
return ImageIO.read(url);
} catch (IOException ee) {
ee.printStackTrace();
return null;
}
}
private BufferedImage toBufferedImage(Image img) {
if (img instanceof BufferedImage) {
return (BufferedImage) img;
}
BufferedImage bimage = new BufferedImage(
img.getWidth(null), img.getHeight(null),
BufferedImage.TYPE_INT_RGB);
// Draw the image on to the buffered image
Graphics2D bGr = bimage.createGraphics();
bGr.drawImage(img, 0, 0, null);
bGr.dispose();
// Return the buffered image
return bimage;
}
public Card getBlankCard() {
return blankCard;
}
public Card getCard() {
return card;
}
public int getCardCount() {
return cardCount;
}
public void incrementCardCount(int increment) {
this.cardCount += increment;
}
}
public class Card {
private final BufferedImage cardImage;
public Card(BufferedImage cardImage) {
this.cardImage = cardImage;
}
public BufferedImage getCardImage() {
return cardImage;
}
}
}
So I have asked a previous question and this is a follow up to it, and I think it deserves its own question. I have this code where a JPanel of a certain size exists in a JScrollPane. The thing is, I want to set my own maximum values to the scroll bars of the JScrollPane which is easy using the bar.setMaximum(value) method. However, there is a weird problem occurring when I scroll the bars without using my mouse itself but rather with the W, A, S, D keys.
The problem is that I set the scroll bars to new maximums, and make a change listener to update the maximums of the scroll bars (because if you looked at my previous question, the scroll bars values were returning to their default max sizes and not the ones I set them to). I thought I solved the problem to the previous question, but now the scroll bars won't scroll all the way, and stop at a certain point. Any ways to fix this?
Note: I don't want to change the JPanel's size that exists in the scroll pane, I just want making the scrolling longer when going from side to side with the W, A, S, D keys. (My unit increment is 1 which is too large for me, so changing the max size of the scroll bars seemed fit as that would decrease an increment’s size overall)
Here is the minimal reproducible (I drew a rectangle in the JPanel map to help see what's going on):
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.event.*;
import java.awt.*;
public class Test implements KeyListener, ChangeListener {
private static JScrollPane view;
public Test() {
create();
}
public static void main(String[] args) {
new Test();
}
public void create() {
JFrame frame = new JFrame(); //make frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1000, 1000);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
SpringLayout layout = new SpringLayout();
JPanel base = new JPanel();
base.setPreferredSize(new Dimension(1000, 1000));
base.setLayout(layout);
JPanel map = new JPanel() {
public void paint(Graphics g) {
super.paint(g);
g.drawRect(0, 0, 995, 100);
}
};
map.setPreferredSize(new Dimension(1000, 1000));
view = new JScrollPane(map);
view.setFocusable(true);
view.addKeyListener(this);
view.setPreferredSize(new Dimension(300, 300));
layout.putConstraint(SpringLayout.HORIZONTAL_CENTER, view, 0, SpringLayout.HORIZONTAL_CENTER, base);
layout.putConstraint(SpringLayout.VERTICAL_CENTER, view, 0, SpringLayout.VERTICAL_CENTER, base);
base.add(view); //add scrollpane to base jpanel
frame.add(base);
frame.setVisible(true);
JScrollBar hBar = view.getHorizontalScrollBar();
JScrollBar vBar = view.getVerticalScrollBar();
hBar.getModel().addChangeListener(this);
vBar.getModel().addChangeListener(this);
hBar.getModel().setMaximum(10*800);
vBar.getModel().setMaximum(10*800);
}
public void stateChanged(ChangeEvent event) { //change max whenever model's max tries to default
BoundedRangeModel model = (BoundedRangeModel) event.getSource();
model.setMaximum(10*800);
}
public void keyPressed(KeyEvent event) { //W, A, S, D keys to change values of jscrollbars
int verticalValue = view.getVerticalScrollBar().getModel().getValue();
int horizontalValue = view.getHorizontalScrollBar().getModel().getValue();
switch (event.getKeyCode()) {
case KeyEvent.VK_W:
view.getVerticalScrollBar().getModel().setValue(verticalValue - 10);
break;
case KeyEvent.VK_S:
view.getVerticalScrollBar().getModel().setValue(verticalValue + 10);
break;
case KeyEvent.VK_A:
view.getHorizontalScrollBar().getModel().setValue(horizontalValue - 10);
break;
case KeyEvent.VK_D:
view.getHorizontalScrollBar().getModel().setValue(horizontalValue + 10);
break;
}
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}
I have been struggling with this for some time. At first, I only used ActionListener, then I added the paintComponent, but I have no idea what to put there. I read some tutorials and used their code as an example, but it still doesn't work. Right now, the end result is the same as it was without PaintComponent.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Scream extends JPanel {
private JButton button = new JButton("OK");
private Color screenColor;
private JPanel panel = new JPanel();
private JFrame frame;
private Dimension screenSize;
private ImageIcon image;
private JLabel label = new JLabel(image);
private int x;
private int y;
private boolean mouseClicked;
public Scream() {
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e ) {
if (e.getSource() == button) {
mouseClicked = true;
frame.getContentPane().add(label);
frame.setSize(image.getIconWidth(), image.getIconHeight());
panel.repaint();
}
}
});
frame = new JFrame ("Existential angst");
screenColor = new Color(150, 100, 0);
panel.setBackground( screenColor );
frame.add(button, BorderLayout.PAGE_END);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1300, 700);
frame.setVisible(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
image.paintComponent(this, g, 1300, 700);
}
public static void main (String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Scream scream = new Scream();
}
});
}
}
If you are trying to dynamically add an image to a panel then you need to add the label to the panel. There is no need for any custom painting.
The basic code for adding components to a visible GUI is:
panel.add(...);
panel.revalidate();
panel.repaint();
Also, don't attempt to set the size of the frame to the size of the image. A frame contains a titlebar and borders. Instead you can use frame.pack();
I noticed a couple of issues:
image is never initialized to anything so it is null, effectively making the label empty. I assume maybe your example was just incomplete?
Once I initialized the image to something, your example still did not work. Turns out adding label without specifying any constraint basically does nothing (I assume since adding a component to a border layout without a constraint puts it in the center where panel already is). When I added the label to BorderLayout.NORTH, everything worked (though resizing the frame to the size of the image makes it only partially visible since the frame includes the OK button)
I want to put my background image at the very bottom in this frame, and the button on top. However the code I wrote below doesn't work. Can anyone see where the problems are?
Another thing is that even though I set the location for my button, it keep showing at the top center on the frame.
Please ignore the comment lines. (I was just guessing, and hoping them will work, but they don't apparently.)
public class Menu extends JFrame{
private JLayeredPane pane;
private JLayeredPane pane2;
public Menu(){
final JFrame f = new JFrame("Chinese Chess");
JButton play = new JButton("Play vs. AI");
f.setLayout(new FlowLayout());
f.setLocationRelativeTo(null);
f.setSize(800, 800);
f.setVisible(true);
f.setResizable(false);
//f.pack();
pane = new JLayeredPane();
pane2 = new JLayeredPane();
f.add(pane);
f.add(pane2);
//background image
JLabel background = new JLabel(new ImageIcon("res/img/background.png"));
background.setLocation(0, 0);
background.setSize(800, 800);
pane.add(background, JLayeredPane.FRAME_CONTENT_LAYER);
pane2.add(play, JLayeredPane.DEFAULT_LAYER);
//pane.moveToBack();
//button PlayAI
play.setLocation(500,500);
play.setPreferredSize(new Dimension(100,50));
//f.setLayout(new FlowLayout());
//frame menu
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//f.getContentPane().add(play);
play.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
new PlayAI();
}
});
}
public static void main(String[] args){
new Menu();
}
Problems/Solutions:
setLocation(...) and setBounds(...) types of calls are ignored by most layout managers. The only way to use them is to set the layout of the container to null via .setLayout(null);
But having said that, while null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
So in sum -- don't do this, don't use null layouts or setBounds, but rather nest JPanels, each using its own layout manager, and thereby create easy to maintain and decent GUI's.
If you want an image to be in the background, then draw it in a JPanel that you use as a container for your GUI components by drawing it in the JPanel's paintComponent(Graphics g) method as has been demonstrated in many many similar questions on this site -- I'll find you some of mine in a second.
If you add any JPanels on top of this image drawing JPanel, be sure that you can see through them by calling setOpaque(false) on these overlying JPanels. Otherwise you'll cover up the image.
Your code has two JFrames when only one is needed. Get rid of the one you don't use.
You call setVisible(true) too early on the JFrame, before components have been added to the GUI -- don't. Call it only after adding everything to the GUI so all display OK.
You're creating two JLayedPanes, and completely covering one by the other by adding them to the JFrame without understanding how the JFrame's BorderLayout handles added components.
I suggest that you not even use one JLayeredPane but instead draw in the JPanel as noted above, and use that as your container.
Your code looks to be opening a completely new GUI window when the play button is pressed, and if so, this can get annoying to the user fast. Consider swapping views instead with a CardLayout.
For example:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
// extend JPanel so you can draw to its background
#SuppressWarnings("serial")
public class Menu2 extends JPanel {
private BufferedImage bgImage = null; // our background image
private JButton playButton = new JButton(new PlayVsAiAction("Play Vs. AI", KeyEvent.VK_P));
public Menu2(BufferedImage bgImage) {
this.bgImage = bgImage;
setLayout(new GridBagLayout()); // center our button
add(playButton);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (bgImage != null) {
g.drawImage(bgImage, 0, 0, this);
}
}
// to size our GUI to match a constant or the image.
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
// if you want to size it based on the image
if (bgImage != null) {
int width = bgImage.getWidth();
int height = bgImage.getHeight();
return new Dimension(width, height);
} else {
return super.getPreferredSize();
}
// if you want to size the GUI with constants:
// return new Dimension(PREF_W, PREF_H);
}
private class PlayVsAiAction extends AbstractAction {
public PlayVsAiAction(String name, int mnemonic) {
super(name); // have our button display this name
putValue(MNEMONIC_KEY, mnemonic); // alt-key to press button
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO code to start program
}
}
private static void createAndShowGui() {
BufferedImage img = null;
String imagePath = "res/img/background.png";
try {
// TODO: fix this -- use class resources to get image, not File
img = ImageIO.read(new File(imagePath));
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
Menu2 mainPanel = new Menu2(img);
JFrame frame = new JFrame("Chinese Chess");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createAndShowGui();
});
}
}
Apart from the solution above... you should create and launch your swing application this way:
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
// Instantiate your JFrame and show it
}
I am trying to change the background color of my tabs in a JTabbedPane. I tried JTabbedPane.setBackgroudAt(0, Color.GRAY) and JTabbedPane.setBackgroud(Color.GRAY) and the foreground too, but nothing happens. I changed the background of the panel inside the tab, still nothing.
Edit 1: I'm using UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); if this can help with the solution
Edit 2: Link to a example, https://www.dropbox.com/s/0krn9vikvkq46mz/JavaApplication4.rar
You can change the background color of the tab using setBackgroundAt(), as shown here.
You can change the background color of the tab's content using setBackground(), as shown here. Typically you have to do this on the tab's content, as the enclosing JTabbedPane background color is obscured by the content.
If you still have trouble, please edit your question to include an sscce based on either example that exhibits the problem you envounter.
Addendum: Combining the methods is also possible:
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
public class JTabbedTest {
private static JTabbedPane jtp;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jtp = new JTabbedPane();
jtp.setPreferredSize(new Dimension(320, 200));
jtp.addTab("Reds", new ColorPanel(0, Color.RED));
jtp.setBackgroundAt(0, Color.RED);
jtp.addTab("Greens", new ColorPanel(1, Color.GREEN));
jtp.setBackgroundAt(1, Color.GREEN);
jtp.addTab("Blues", new ColorPanel(2, Color.BLUE));
jtp.setBackgroundAt(2, Color.BLUE);
f.add(jtp, BorderLayout.CENTER);
f.pack();
f.setVisible(true);
}
});
}
private static class ColorPanel extends JPanel implements ActionListener {
private final Random rnd = new Random();
private final Timer timer = new Timer(1000, this);
private Color color;
private Color original;
private int mask;
private JLabel label = new JLabel("Stackoverflow!");
private int index;
public ColorPanel(int index, Color color) {
super(true);
this.color = color;
this.original = color;
this.mask = color.getRGB();
this.index = index;
this.setBackground(color);
label.setForeground(color);
this.add(label);
timer.start();
}
#Override
public void actionPerformed(ActionEvent e) {
color = new Color(rnd.nextInt() & mask);
this.setBackground(color);
jtp.setBackgroundAt(index, original);
}
}
}
most of method for JTabbedPane is protected in the API, and not accesible from Swing methods
have to look for Custom XxxTabbedPaneUI, override these methods, and could be accesible from outside
correct way would be to implement Custom Look & Feel only, part of them override JTabbedPane
example for Custom XxxTabbedPaneUI
You should consider using a Look and Feel that does what you want, or failing that, changing the default UIManger settings for a JTabbedPane:
UIManager.put("TabbedPane.background", Color.GRAY);
If you opt for the latter, it must be done before you create your GUI.
For more on this, please see Rob Camick's excellent blog on the subject: UIManager Defaults.
Edit: I was wrong. It should be:
UIManager.put("TabbedPane.unselectedBackground", Color.GRAY);
But note that this may not work with every Look and Feel.
It may be a problem that there is nothing added yet to the tab.
Try setting the content manager of the content panel to BorderLayout, adding a JPanel with BorderLayout. Center and then coloring that panel.