good day
I am trying to change the color of the box text (jtextfile) that brings the built-in jdatechooser
I am developing an application where the white background of the jdatechooser does not match at all, I have changed the background color of both the jtextfile and the button of the jdatechooser with the following code:
for( Component c : jdate.getComponents()){
((JComponent)c).setBackground(new Color(20,25,34));
}
thus
My current problem is that the background color that I need is very dark, and the date text is black, currently in the image there is a selected date, you just don't see anything.
I have tried to change the text to white without success.
try the same method without getting the solution
for( Component text : jdate.getComponents()){
((JComponent)text).setForeground(new Color(255,255,255));
}
I also tried removing the code that I put at the beginning for the background thinking that this could be preventing the change of the text color but it did not work either.
Try these other ways to get the change:
JTextFieldDateEditor dateChooserEditor = ((JTextFieldDateEditor)jdate.getDateEditor());
dateChooserEditor.setForeground(new Color(255, 255, 255));
Of course the easy way didn't work either:
jdate.setForeground(Color.WHITE);
The only way I have managed to change the color of the text is to disable the text field and leave the button enabled to choose the date for the button and it cannot be written in the text box.
jdate.getDateEditor().setEnabled(false);
((JTextFieldDateEditor) jdate.getDateEditor ())
.setDisabledTextColor(Color.WHITE);
The problem with this, in addition to not being allowed to write the date manually, I also lose the desired background color.
as shown here
Any solution for this ?, preferably without having to disable the text box.
Thanks in advance!.
I propose the following solution.
Class JTextFieldDateEditor extends JFormattedTextField. Hence the foreground color is a bound property which means that you can listen for changes to it. Therefore you can add a PropertyChangeListener. If the new foreground color is black, simply change it to white.
Here is a small application that demonstrates.
import com.toedter.calendar.IDateEditor;
import com.toedter.calendar.JDateChooser;
import com.toedter.calendar.JTextFieldDateEditor;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
public class JdcTest0 implements Runnable {
private JFrame frame;
private JDateChooser jdate;
#Override
public void run() {
showGui();
}
private JPanel createDateChooser() {
JPanel panel = new JPanel();
jdate = new JDateChooser();
IDateEditor dateEditor = jdate.getDateEditor();
if (dateEditor instanceof JTextFieldDateEditor) {
JTextFieldDateEditor txtFld = (JTextFieldDateEditor) dateEditor;
txtFld.setBackground(Color.BLACK);
txtFld.addPropertyChangeListener("foreground", event -> {
if (Color.BLACK.equals(event.getNewValue())) {
txtFld.setForeground(Color.WHITE);
}
});
}
panel.add(jdate);
return panel;
}
private void showGui() {
frame = new JFrame("JDC");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(createDateChooser(), BorderLayout.PAGE_START);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new JdcTest0());
}
}
Note that class JTextFieldDateEditor changes its foreground color to red if the date is invalid and to green if the date is valid. If you want to handle those colors as well, then the red color is java.awt.Color#red, i.e. [255, 0, 0] and the green is a custom color [0, 150, 0].
Related
How do I make a JLabel text vertically and horizontally aligned to the center?
I have to make use of setHorizontalTextPosition and setVerticalTextPosition. Can this be achieved by using these 2?
I have tried but the text remains at the top itself.
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
public class label extends JFrame
{
private JLabel label;
public label() //constructor
{
super("Simple GUI");
setLayout(new FlowLayout());
label=new JLabel("Centered JLabel");
label.setHorizontalTextPosition(SwingConstants.CENTER);
label.setVerticalTextPosition(SwingConstants.CENTER);
add(label);
}
}
I have tried but the text remains at the top itself.
You have two problems:
Andrew addressed the first problem. You are using the wrong method.
Next you are using the wrong layout. The FlowLayout only display components on a single line so the component will always be at the top. Don't change the layout manager. The default layout manager for a JFrame is the BorderLayout. When you add a component to the CENTER (which is the default when you don't specify a constraint), the component will be sized to fill the entire frame. Then the "alignment" properties will control the position of the text within the size allocated to the label.
Or a different option is to use a GridBagLayout. Then you don't need to play with alignment options of the component:
setLayout( new GridBagLayout() );
add(label, new GridBagConstraints());
Try both options as both may be effective in different situations.
Read the Swing tutorial on Layout Managers to better understand how each layout manager works.
I'm very sorry to don't know why the setHorizontalTextPosition method and the setVerticalTextPosition method doesn't work.
But, I'll let you know that there're several ways to sort the text in the label by inserting parameters an alignment with String when we create the label.
First of all, camickr's answer is the best answer, Because Swing was designed to be used with layout managers!!
Please remember that the most recommended method is to apply GridBagLayout() to the Layout of JFrame by camickr.
This answer is intended to inform you that
This method is also possible, but not recommended in the normal case
Using this method is not recommended because changing the size of the frame
keeps the components in place, but it could give you a little help
when it is indicated that the size and location of components in the
container are used in a way that can be used in special cases, such as
when they need to be fixed without external impact.
To get a better idea of the problem, I'll simply change the code that you uploaded to me so that it can be executed.
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import java.awt.Color;
public class StackOver extends JFrame
{
private JLabel label;
public StackOver() //constructor
{
super("Simple GUI");
setLayout(null);
setSize(500,300);
label=new JLabel("Centered JLabel", JLabel.CENTER);
/*
label.setHorizontalTextPosition(SwingConstants.CENTER);
label.setVerticalTextPosition(SwingConstants.CENTER);*/
add(label);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new StackOver();
}
}
Hmm, let's put some color in JLabel's background to find out more.
label.setOpaque(true); //Transparency Settings
label.setBackground(Color.pink); //Specify background color
//to use 'Color' class, We must import java.awt.Color;
the JFrame setting was set to FlowLayout()which makes the location and size of components were fixed, so we couldn't see it working!
So now we're going to go through the next two processes.
1) Changing JFrame's layout to null to use Absolute Layout ("not recommended, just a case")
2) Changing the size and location of the JLabel
after the progress we can see that the text alignment works!
1) Changing JFrame's Layout
the following link: Layout Manager shows that there are so many Layouts outside of FlowLayout.
Swing is designed to use the layout manager, so of course you should use one of the Layout above link.
But, to use an interesting way that fix the location and size of components absolutely We will switch to setLayout(null);!
2) Changing the size and location of the JLabel
We can directly change the size and position of JLabel with setBounds(int startX, int startY, int Width, int Height) method!
import java.awt.FlowLayout;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import java.awt.Color;
public class StackOver extends JFrame
{
private JLabel label;
public StackOver() //constructor
{
super("Simple GUI");
setLayout(null);
setSize(500,300);
label=new JLabel("Centered JLabel", JLabel.CENTER);
// Since it also sets the size of the JLabel,
//let's use the constructor to set the alignment of the text inside the JLabel.
label.setOpaque(true); //Transparency Settings
label.setBackground(Color.pink); //Specify background color
//to use 'Color' class, We must import java.awt.Color;
Rectangle r = this.getBounds(); //to get Frame Size
label.setBounds(r.x+100, r.y+100, r.width-200, r.height-200);
/*
label.setHorizontalTextPosition(SwingConstants.CENTER);
label.setVerticalTextPosition(SwingConstants.CENTER);*/
add(label);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new StackOver();
}
}
Now we can see the text of JLabel in the middle as intended!
This method can directly fix the size and location of all components (ex buttons), but the location and size of the components are fixed even if the window size of the JFrame changes after the program runs.
so If you really want set components Absolutely by this way, you rather to set JFrame Resizable false by adding below code on JFrame's code
this.setResizable(false);
I hope the answer was helpful to you and have a peaceful day!
Sorry if this is a really stupid question but I can't figure out how to set the size of a JButton. I'm trying to create a custom JButton class which can be called from anywhere with custom text to make things easier. I am also trying to set a background image which doesn't appear to be working either.
I have tried using this.setSize(1000, 1000) (surely this should work) but this does nothing at all.
Here is my code:
package menu;
import javax.swing.*;
#SuppressWarnings("serial")
public class Button extends JButton
{
public Button(String name)
{
ImageIcon background = new ImageIcon("/assets/buttons/menu.png"); //Is this how you set a background image for a button?
this.setText(name);
this.setIcon(background);
this.setLayout(null); //This hasn't made a difference
this.setSize(300, 80); //This does nothing
}
}
try
import javax.swing.JButton;
public class replaceButton **extends JButton**
{
public replaceButton(String name)
{
this.setText(name);
ImageIcon background = new ImageIcon("/assets/buttons/menu.png");
this.setIcon(background);
this.setSize(1000,1000);
}
}
by extending JButton you give it the properties of a button.
make sure you dont have any layout by adding this to the JFrame
this.setLayout(null);
else the button will be adjusted to the layout
see http://docs.oracle.com/javase/tutorial/uiswing/layout/border.html
I'm going to enhance an application with a Swing UI, to allow the user to pick colors so they're not stuck with the default color choices.
It is common for other applications to have shaded rectangles drawn on each button that activates a color selector, with the rectangle's color changing accordingly when a new color is selected. I am trying to achieve the same effect by placing a small JPanel with the selected color on the button, but that results in a tiny square in the middle of the button, instead of filling most of the surface of the button.
I figure another way would be to dynamically generate rectangular icons with the colors and then add the appropriate icon to each button, but surely there must be a simpler way?
put there JButton.setIcon with expected Rectangle, for example
EDIT
I am trying to achieve the same effect by placing a small JPanel with the selected color on the button, but that results in a tiny square in the middle of the button, instead of filling most of the surface of the button.
only JFrame (BorderLayout) and JPanel (FlowLayout) have got pre-implemented LayoutManager, for rest of JComponents (add one JComponent to the another JComponent) you have to define LayoutManager, please read this thread
Here is an example using setBackground that works for me:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public static void main(String... args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
final JButton button = new JButton("Hello");
button.setOpaque(true);
panel.add(button);
button.setBackground(Color.RED);
button.setOpaque(true);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Color c = JColorChooser.showDialog(button, "Choose a color", button.getBackground());
if (c != null) {
button.setBackground(c);
}
}
});
frame.setContentPane(panel);
frame.setPreferredSize(new Dimension(800, 600));
frame.pack();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
}
}
Every swing component is drawn using the JComponent.drawComponent(...) method, you can override the default behavior if you want. For example, to make a panel like you suggest. It is worth noting though, that you can change a jpanels background color to achieve the exact same thing.
JColorChooser chooser = new JColorChooser(Color.BLACK);
chooser.setVisible(true);
Color color = chooser.getColor();
if (color!=null) {
colorPanel.setBackground(color);
}
Where colorPanel would be your JPanel indicating your color.
I'm super confused with what exactly models are supposed to do in java swing. At present I'm basically trying to create a model for JButton to detect if it isPressed(); My essential goal of the model is to do something like this:
if(myButton.isPressed() ) {
myButton.setBackground(Color.RED);
}
else{//when any other button is pressed?
myButton.setBackground(Color.WHITE);
}
At present my code is something like this:
numberButton = new JButton("Num");
numberButton.setBounds(20,40,80,30);
numberButton.addChangeListener(new ChangeListener() {
public void stateChanged (ChangeEvent e){
if (model.isPressed() ){
doColorChange(model);
}
}
});
I understand that this is totally wrong, but I have no idea where, and I haven't found a tutorial that really explains what I'm doing wrong or why I need a model for this at all.
Please help me restore my sanity! Thanks a lot!
Use radio buttons in a button group.
import java.awt.image.BufferedImage;
import java.awt.*;
import javax.swing.*;
import java.net.URL;
import javax.imageio.ImageIO;
class RedAndWhite {
public static Image getColoredImage(Color color, int size) {
BufferedImage bi = new BufferedImage(
size,
size,
BufferedImage.TYPE_INT_RGB);
Graphics g = bi.getGraphics();
g.setColor(color);
g.fillRect(0,0,size,size);
g.dispose();
return bi;
}
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Image red = getColoredImage(Color.RED, 32);
Image white = getColoredImage(Color.WHITE, 32);
JPanel p = new JPanel(new GridLayout(1,0,5,5));
ButtonGroup bg = new ButtonGroup();
for (int ii=0; ii<6; ii++) {
JRadioButton b = new JRadioButton();
b.setSelectedIcon(new ImageIcon(red));
b.setIcon(new ImageIcon(white));
b.setContentAreaFilled(true);
bg.add(b);
p.add(b);
}
JOptionPane.showMessageDialog(null, p);
}
});
}
}
I think what you want is register an ActionListener or Action with the button in order to handle button presses, right?
Edit: rereading your answer, it seems you want to highlight the button that is being pressed, right? In that case, try to use your own button ui (subclass the one of the look and feel you're using). BasicButtonUI has a method protected void paintButtonPressed(Graphics g, AbstractButton b) that you could override to apply the highlight when the button is being pressed.
there are follows ways how to make JButton nicer
1) most nicest way is painting only Borders from ButtonModel on Mouse events
2) override whole BasicButtonUI with all rellevant Look and Feels
3) put there Icons and override all possible methods implemented in JButton API
4) best at all would be implement Custom Look and Feel
5) create Custom JComponent based on JLabel/JComponent
I always took it that the ButtonModel is intended (mostly) for use by the UI class to render the button in its pressed/not-pressed/armed/selected/... state and track changes to that state.
If you simply want to paint the button red (that is waht you want?) while it is pressed your solution seems fine to me.
If you have a Toggle Button (that remains pressed after it has been clicked to indicate a "selected" state, you might want to use an ItemListener and check for
ItemEvent.ITEM_STATE_CHANGED == ItemEvent.SELECTED // paint red
ItemEvent.ITEM_STATE_CHANGED == ItemEvent.DESELECTED // paint white
If you want to execute application logic when the button is clicked, use an ActionListener.
I have a JButton that I would like to change the background color of to white. When using the Metal Look And Feel, I achieve the desired effect with setBackground:
Unfortunately, the concept of "background color" is different when using the Windows LAF; the background color is the color drawn around the button:
I would like to use the Windows LAF, but allow the button color of this JButton to be changed to white. How do I do this?
You'll have to decide if it's worth the effort, but you can always create youe own ButtonUI, as shown in this example due to #mKorbel.
I use JDK 6 on XP. It looks like the Window UI doesn't follow the normal painting rules in more ways than 1. As you noticed setBackground() doesn't work. You should be able to do custom painting by telling the component not to fill in the content area:
import java.awt.*;
import javax.swing.*;
public class ButtonBackground extends JFrame
{
public ButtonBackground()
{
setLayout( new FlowLayout() );
JButton normal = new JButton("Normal");
add(normal);
JButton test1 = new JButton("Test 1")
{
#Override
public void paintComponent(Graphics g)
{
g.setColor( Color.GREEN );
g.fillRect(0, 0, getSize().width, getSize().height);
super.paintComponent(g);
}
};
test1.setContentAreaFilled(false);
add(test1);
}
public static void main(String[] args)
{
try
{
// UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
}
catch (Exception e2) {}
ButtonBackground frame = new ButtonBackground();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
}
When you run the code as is it seems to work properly. That is when you click on the button you see the Border change. However is you run with the Windows XP LAF, the Border never changes to you don't see the button click effect.
Therefore, I guess the issue is with the WindowUI and you would need to customize the UI which is probably too complex to do so I don't have a solution.
but I still think that (modified but by Darryl) is correct UIManager.get("Button.gradient"), because would be crossplatform
EDIT: correct answer would be - Nimbus or some Custom L&F, why reinvent the wheel (by Rob)
Your best option is using SwingX:
JXButton allows you to set a Painter for the background with .setBackgroundPainter(Painter) using a MattePainter achieves exactly what you want. Having that JXButton extends from JButton, the changes are minimal in your code:
Color bg = new Color(new Random().nextInt(16777215)); // Random color
JButton button = new JButton();
button.setBackground(bg);
would become
JXButton button = new JXButton();
button.setBackgroundPainter(new MattePainter(bg));
instead of messing with the button's background color, could you do whatever indication you're trying to show a different way?
displaying an Icon, making the button bold instead of plain text, etc.
Indicating something only through a different background color isn't always obvious, and depending on the user's system colors, may be jarring, or invisible.
for example, what if the user is running windows in "high contrast" mode?