how to change Jslider value and pass to paintComponent? - java

i am developing an application in which Brightness of image change as per user change the value of JSlider.
Jslider display on window but image is not loaded and i also don't know how to pass value of JSlider to paintComponent() method.
my code :
public class Neo_2010_Slider1 extends JFrame
{
private static final long serialVersionUID = 1L;
private Container container ;
private JSlider slider1 ;
private JLabel lbl1 ;
private JPanel panel1 ;
private JTextField txt1 ;
public Neo_2010_Slider1() {
super("Slider");
setAlwaysOnTop(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBackground(new Color(14555));
setSize(new Dimension(400,400));
setResizable(true);
container = getContentPane();
BorderLayout containerLayout = new BorderLayout();
container.setLayout(containerLayout);
lbl1 = new JLabel("Slider 1");
/****************** TextField Properties ********************************/
txt1 = new JTextField(4);
slider1 = new JSlider(JSlider.HORIZONTAL,0,1000,0);//direction , min , max , current
slider1.setFont(new Font("Tahoma",Font.BOLD,12));
slider1.setMajorTickSpacing(100);
slider1.setMinorTickSpacing(25);
slider1.setPaintLabels(true);
slider1.setPaintTicks(true);
slider1.setPaintTrack(true);
slider1.setAutoscrolls(true);
slider1.setPreferredSize(new Dimension(500,500));
slider1.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
txt1.setText(String.valueOf(slider1.getValue()));
repaint();
}
});
txt1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try
{
slider1.setValue(Integer.parseInt(txt1.getText()));
}
catch(Exception ex)
{
txt1.setText("ERROR");
txt1.setToolTipText("Set Value in Range between 0 - 1000 ") ;
}
}
});
this.addFocusListener(new FocusListener() {
#Override
public void focusLost(FocusEvent e){
}
#Override
public void focusGained(FocusEvent e) {
txt1.setText(String.valueOf(slider1.getValue()));
}
});
panel1 = new JPanel();
container.add(panel1, BorderLayout.WEST);
panel1.add(lbl1);
panel1.add(txt1);
panel1.add(slider1);
setVisible(true);
}
public void paintComponent(Graphics g){
Graphics2D g2d=(Graphics2D)g;
try{
BufferedImage src=ImageIO.read(new File("src.jpg"));
BufferedImage dest=changeBrightness(src,0.5f);
g2d.drawImage(dest,0,0,this);
ImageIO.write(dest,"jpeg",new File("dest.jpg"));
}catch(Exception e){
e.printStackTrace();
}
}
public BufferedImage changeBrightness(BufferedImage src,float val){
RescaleOp brighterOp = new RescaleOp(val, 0, null);
return brighterOp.filter(src,null); //filtering
}
public static void main(String args[])
{
new Neo_2010_Slider1();
}
}
i also don't know that where to pass paintComponent method..
if anyone knows then please guide me.

I'm not sure what it is you how to gain, but JFrame doesn't have a paintComponent method, so it will never be called.
What I would do, instead is
Load the source image as soon as you can and store it in variable (masterImage for example)
Use a JLabel to show the image
Use a javax.swing.Timer with a short delay (so 125 milliseconds) set so it won't repeat. Each time the JSlider's stateChanged event is raised, I would restart this timer.
When the timer finally triggers, I would update the "master" image's brightness and apply teh result to "image" JLabel's as it's icon.
The reason for the timer is the fact that the operation of applying the brightness can not only take time, but can increase the amount of memory the application consumes. You will want to reduce this to the absolute minimum if you can

to get the value of a JSlider, you should add a changelistener.
slider.addChangeListener(new ChangeListener(){
public void stateChanged(ChangeEvent e) {
// handle change
JSlider source = (JSlider)e.getSource();
methodeToHandleChange( (int) source.getValue() );
}
});
see also how to use a sliders
paintComponent
the paintComponent method is a protected method, so it can not be called from the outside. However it is part of the painting mechanisme that can be invoked by calling the repaint method.
slider.repaint();

Related

Subtle differences between java swing objects

I am having some difficulty figuring out why there is a difference between the results I see on the Title Screen and the Setup Screen. I copy/pasted the majority of the code before tweaking each... it clearly has to do with something in my outer frame, but I don't know what. The problem I am seeing is that although the Title Screen comes up at the correct size of 1024x768 with the background correctly displayed, the Setup Screen comes up as a very small window as though I had not just set it's size. The background image is also only shown in that sliver of space, even if the box is resized.
I have removed all of the elements inside of Title Screen but it still maintains its size. Can someone help? Thanks
OuterFrame
public class OuterFrame extends JFrame {
public OuterFrame(String windowHeading) {
int WIDTH = 1024;
int HEIGHT = 768;
final Dimension screenSize = new Dimension(WIDTH,HEIGHT);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
JPanel title = new TitleScreen();
title.setLayout(new BoxLayout(title, BoxLayout.PAGE_AXIS));
JButton matchButton = new JButton("New Match");
//Add action listener to button
matchButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//Execute when button is pressed
removeAll();
JPanel setupScreen = new SetupScreen();
add(setupScreen);
pack();
}
});
JButton exitButton = new JButton("Exit to Windows");
//Add action listener to button
exitButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//Execute when button is pressed
System.exit(0);
}
});
matchButton.setAlignmentX(title.CENTER_ALIGNMENT);
exitButton.setAlignmentX(title.CENTER_ALIGNMENT);
title.setPreferredSize(screenSize);
title.add(matchButton);
title.add(Box.createRigidArea(new Dimension(0,25)));
title.add(exitButton);
add(title);
pack();
}
}
Title Screen
public class TitleScreen extends JPanel {
public BufferedImage background;
public TitleScreen() {
try {
InputStream is = new BufferedInputStream(new FileInputStream("images/datascreen.png"));
Image image = ImageIO.read(is);
background = (BufferedImage)image;
} catch (Exception a) {
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.drawImage(background,0,0,1024,768,null);
}
}
SetupScreen
public class SetupScreen extends JPanel {
public BufferedImage background;
public SetupScreen() {
try {
InputStream is = new BufferedInputStream(new FileInputStream("images/datascreen.png"));
Image image = ImageIO.read(is);
background = (BufferedImage)image;
} catch (Exception a) {
}
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.drawImage(background,0,0,1024,768,null);
}
}
Sorry about the formatting.. I can't for the life of me make it keep the indention I use in my code.
Edit:
#Override
public Dimension getPreferredSize() {
return new Dimension(1024, 768);
}
I added the above to both the title and the setup classes, as well as removing the hard coded resize. The issue still occurs - the window is sized correctly for the title but not the setup. Any help would be appreciated..
Read the Swing tutorial on Custom Painting for the basics. In this case the problem is that you don't override the getPreferredSize() method of your custom component, so the layout manager basically uses 0.
The reason your first screen displays is because you hardcoded:
title.setPreferredSize(screenSize);
This is a no-no (for too many reasons to go into detail here). The component should return its preferred size as mentioned above and then the pack() statement will work properly.
Figured out that the problem was the removeAll() statement. I added getContentPane. to it and it worked fine.

Java ComponentResized - Detect whether user resized the window or it was resized programatically

I have a JFrame in which I remove and add components and each time I do this, I resize the frame accordingly. I added a Component Listener but of course it gets triggered both by the user resizing the window and also by my setSize() methods.
Is there any way to see from the ComponentEvent whether the user resized the window or I did through setSize()?
The posible solutions I found are:
1. Use a flag - boolean resizing - which I set to true before setSize() and to false after that.
2. Add a mouseDragged listener and compare sizes before and after the drag.
The second one is definitely not a good choice. The first one would work but I would like to know if I can find in a simple way whether the user is the one who resized the window or not.
I resize the frame accordingly
Whats wrong with using pack()?
I remove and add components and each time I do this,
Then this is where you should set your Boolean value:
programResize == true:
panel.add(...);
frame.setSize(...); // this should cause the ComponentListener to fire
// the ComponentListener would then use programResize == false;
Or a better option option could be:
component.removeComponentListener(...);
panel.add(...);
frame.setSize(...);
component.addComponentListener(...);
I like this approach better because all the logic based on the manual update is self contained in one place and there is no need to define a Boolean variable.
Is there any way to see from the ComponentEvent whether the user
resized the window or I did through setSize()?
yes it is, use boolean flag reseted by Swing Timer
in the case that user resized window then ComponentListener firing a new event per every pixel, bunch of events
by determine the contianer set(Xxx)Size is this event fired only once time
example about events from ComponentListner
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
public class ComponentEventDemo extends JPanel
implements ComponentListener, HierarchyListener,
ItemListener {
private JFrame frame;
private static final long serialVersionUID = 1L;
private JTextArea display;
private JLabel label;
private JButton button = new JButton("Change Size");
private String newline = "\n";
public ComponentEventDemo() {
display = new JTextArea();
display.setEditable(false);
JScrollPane scrollPane = new JScrollPane(display);
scrollPane.setPreferredSize(new Dimension(350, 200));
label = new JLabel("This is a label", JLabel.CENTER);
label.addComponentListener(this);
JCheckBox checkbox = new JCheckBox("Label visible", true);
checkbox.addItemListener(this);
checkbox.addComponentListener(this);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Dimension dim = frame.getPreferredSize();
if (!dim.equals(new Dimension(800, 600))) {
frame.setPreferredSize(new Dimension(800, 600));
frame.pack();
} else {
frame.setPreferredSize(new Dimension(400, 300));
frame.pack();
}
}
});
JPanel panel = new JPanel(new GridLayout(1, 3));
panel.add(label);
panel.add(checkbox);
panel.add(button);
panel.addComponentListener(this);
frame = new JFrame("ComponentEventDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(scrollPane, BorderLayout.CENTER);
frame.add(panel, BorderLayout.PAGE_END);
frame.pack();
frame.setVisible(true);
}
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
label.setVisible(true);
label.revalidate();
label.repaint();
} else {
label.setVisible(false);
}
}
protected void displayMessage(String message) {
//If the text area is not yet realized, and
//we tell it to draw text, it could cause
//a text/AWT tree deadlock. Our solution is
//to ensure that the text area is realized
//before attempting to draw text.
// if (display.isShowing()) {
display.append(message + newline);
display.setCaretPosition(display.getDocument().getLength());
//}
}
#Override
public void componentHidden(ComponentEvent e) {
//displayMessage(e.getComponent().getClass().getName() + " --- Hidden");
}
#Override
public void componentMoved(ComponentEvent e) {
//displayMessage(e.getComponent().getClass().getName() + " --- Moved");
}
#Override
public void componentResized(ComponentEvent e) {
displayMessage(e.getComponent().getClass().getName() + " --- Resized ");
}
#Override
public void componentShown(ComponentEvent e) {
//displayMessage(e.getComponent().getClass().getName() + " --- Shown");
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ComponentEventDemo componentEventDemo = new ComponentEventDemo();
}
});
}
#Override
public void hierarchyChanged(HierarchyEvent e) {
displayMessage(e.getComponent().getClass().getName() + " --- Hierarchy changed");
}
}

change the size of JTextField on KeyPress

I have to extend the size of JTextField on KeyPressed event as user enter the text in textfield.please give me some idea how to achieve this?
thanks in advance
Okay, jumping for it :-)
Let's assume the question is
How to adjust a JTextField's width to always fit its content width?
Usual collaborators
a LayoutManager which sizes its children at their pref size, f.i. FlowLayout
JTextField reports its pref size fitted to content
auto-magical resize expected
Quick example:
JTextField field = new JTextField("something");
JComponent parent = new JPanel(); // has FlowLayout by default
parent.add(field);
frame.add(parent);
// just to ensure it's bigger
frame.setSize(400, 400);
type ... and nothing happens: size remains at initial size. That's surprise: for some reason, the field's auto-validation simply doesnt't happen. In fact, a manual revalidate of the field on receiving a change notification (Note: the only correct listener type here is a DocumentListener) doesn't change the field as well:
final JTextField field = new JTextField("something");
DocumentListener l = new DocumentListener() {
private void updateField(JTextField field)
// has no effect
field.revalidate();
}
#Override
public void removeUpdate(DocumentEvent e) {
updateField(field);
}
#Override
public void insertUpdate(DocumentEvent e) {
updateField(field);
}
#Override
public void changedUpdate(DocumentEvent e) {
}
};
field.getDocument().addDocumentListener(l);
JComponent parent = new JPanel(); // has FlowLayout by default
parent.add(field);
frame.add(parent);
// just to ensure it's bigger
frame.setSize(400, 400);
#Gagandeep Bali found out that it's the parent that needs to be revalidated:
private void updateField(JTextField field) {
field.getParent().revalidate();
}
Unexpected, so the next question is the notorious why? Here: why doesn't the invalidate bubble up the container hierarchy until it finds a validateRoot? The answer is in the api doc:
Calls to revalidate that come from within the textfield itself will be handled by validating the textfield, unless the textfield is contained within a JViewport, in which case this returns false.
Or in other words: it's not bubbled up because the field itself is a validateRoot. Which leaves the other option to override and unconditionally return false:
JTextField field = new JTextField("something") {
#Override
public boolean isValidateRoot() {
return false;
}
};
JComponent parent = new JPanel(); // has FlowLayout by default
parent.add(field);
frame.add(parent);
// just to ensure it's bigger
frame.setSize(400, 400);
The price to pay for this, is that the scrolling doesn't work - which isn't a big deal in this context, as the text always fits into the field. Or implement slightly more intelligent, and return true if the actual width is less than the pref.
The best way I can think of is to add one CaretListener to the JTextField concerned, and with the change in the length of the Document, you Increase/Decrease the columns of the said JTextField by calling it's setColumns(...), which inturn will Increase/Decrease the size of the JTextField
Here is one example to show you, how to achieve this :
import java.awt.*;
import javax.swing.*;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
public class JTextFieldColumnExample
{
private int columns = 1;
private JTextField tfield;
private void displayGUI()
{
JFrame frame = new JFrame("JTextField Columns Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPanel contentPane = new JPanel();
tfield = new JTextField();
tfield.setColumns(columns);
tfield.addCaretListener(new CaretListener()
{
public void caretUpdate(CaretEvent ce)
{
int len = tfield.getDocument().getLength();
if (len > columns)
tfield.setColumns(++columns);
else
{
if (--columns != 0)
tfield.setColumns(columns);
else
{
columns = 1;
tfield.setColumns(columns);
}
}
contentPane.revalidate();
contentPane.repaint();
}
});
contentPane.add(tfield);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new JTextFieldColumnExample().displayGUI();
}
});
}
}
1) never to use KeyListener for JTextComponent, use DocumentListener, nothing else
2) you can to use FontMetrics, TextLayout, SwingUtilities
3) after resize you have to notify LayoutManager,
4) if is there only JTextField then to use pack() for Top-Level Container,
5) otherwise (in the case that there is more than one JPanel nested other JComponents) you have to re_layout whole Container with revalidate()and repaint() then
call pack() to the Top-Level Container if you want to resize continiously with its contens
don't call pack() to the Top-Level Container if you don't want to resize, but required usage of JScrollPane
6) in the case that value of String could be very long, then to use proper JTextComponent with supporting multiline output to the GUI, to use JTextArea (in JScrollPane) rather than plain JTextField
Depends if you are using a LayoutManager or not. If not, attach a KeyListener to the JTextField and on keyRelease you need to calculate the length of the String (in pixels) and determine if the field needs to be updated
addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
updateField();
}
public void insertUpdate(DocumentEvent e) {
updateField();
}
public void removeUpdate(DocumentEvent e) {
updateField();
}
public void updateField() {
FontMetrics fm = getFontMetrics(getFont());
String text = getText();
int length = fm.stringWidth(text);
Dimension size = getPreferredSize();
Insets insets = getInsets();
if (length < min) {
size.width = min;
} else {
size.width = length + (insets.left + insets.right);
}
setSize(size);
invalidate();
repaint();
}
});
Possibly a more sensible solution might be:
addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
updateField();
}
public void insertUpdate(DocumentEvent e) {
updateField();
}
public void removeUpdate(DocumentEvent e) {
updateField();
}
public void updateField() {
setColumns(getText().length());
}
});
I would also pay attention to what kleopatra & mKorbel have to say. While KeyListener might seem like a good idea, there are just to many situation's where it won't be notified - setText is the major one.

how to set new text in JTextField after creation?

I have a jTextField , and I set it's value to a certain sum when I create the frame.
Here is the initiation code:
totalTextField.setText(
itemsPriceTextField.getText() +
Float.toString(orderDetails.delivery)
);
This textfield should show a sum of items selected by the user.
The selection is done on a different frame, and both frames are visible / invisible
at a time.
The user can go back and forth and add / remove items.
Now, every time i set this frame visible again, I need to reload the value set to that field
(maybe no changes were made, but if so, I need to set the new correct sum) .
I'm quite desperate with it.
Can anyone please give me a clue?
Thanks in advance! :)
Before setting the frame visible again, one should update the fields with the new values / states.
something like:
jTextField.setText("put your text here");
jRadioButton.setSelected(!isSelected());
.
/* update all you need */
.
jFrame.setVisible(true);
The frame will come up with the new values / states.
Add a WindowListener to the frame. Then you can handle the windowActivated event and reset the text of the text field.
See How to Write Window Listeners.
Use a DocumentListener triggering the JTextField public void setText(String t)
Here an example with DocumentListener:
public class SetTextInJTextField extends JFrame implements DocumentListener {
JTextField entry;
JTextField entryToSet = new JTextField();
public SetTextInJTextField() {
createWindow();
entry.getDocument().addDocumentListener(this);
}
private void createWindow() {
JFrame frame = new JFrame("Swing Tester");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
createUI(frame);
frame.setSize(560, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void createUI(final JFrame frame) {
JPanel panel = new JPanel();
entry = new JTextField();
entryToSet = new JTextField();
LayoutManager layout = new BoxLayout(panel, BoxLayout.PAGE_AXIS);
panel.setLayout(layout);
panel.add(this.entry);
panel.add(entryToSet);
frame.getContentPane().add(panel, BorderLayout.CENTER);
}
public void setTextInTargetTxtField() {
String s = entry.getText();
entryToSet.setText(s);
}
// DocumentListener methods
public void insertUpdate(DocumentEvent ev) {
setTextInTargetTxtField();
}
public void removeUpdate(DocumentEvent ev) {
setTextInTargetTxtField();
}
public void changedUpdate(DocumentEvent ev) {
}
public static void main(String args[]) {
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new SetTextInJTextField().setVisible(true);
}
});
}
}
inspired from: https://docs.oracle.com/javase/tutorial/displayCode.html?code=https://docs.oracle.com/javase/tutorial/uiswing/examples/components/TextFieldDemoProject/src/components/TextFieldDemo.java
related lesson: https://docs.oracle.com/javase/tutorial/uiswing/components/textfield.html

How do I call an actionlistener while the slider is moving, not just when I let go of the mouse?

class AngleSlider implements ChangeListener {
public void stateChanged(ChangeEvent e) {
JSlider source = (JSlider) e.getSource();
if (!source.getValueIsAdjusting()) {
double dAngle = (double)source.getValue();
pnlCannon.dCannonAngle=Math.toRadians(dAngle);
pnlCannon.repaint();
}
}
}
This is our current event listener. Is there a different listener required to do what I want?
No, you will only need to remove the getValueIsAdjusting() check. So, this will repaint your cannon when you move your mouse:
class AngleSlider implements ChangeListener {
public void stateChanged(ChangeEvent e) {
JSlider source = (JSlider) e.getSource();
double dAngle = (double)source.getValue();
pnlCannon.dCannonAngle=Math.toRadians(dAngle);
pnlCannon.repaint();
}
}
This is another example that shows the same, it will print the value of the slider as you move it:
public static void main(String[] args) {
JFrame frame = new JFrame("Test");
JSlider slider = new JSlider();
slider.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent ce) {
System.out.println(((JSlider) ce.getSource()).getValue());
}
});
frame.add(slider);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setVisible(true);
}
The !source.getValueIsAdjusting() is preventing the update code form executing.
Why do you think that condition is necessary?

Categories

Resources