JScrollBar: Stop knob moving further upon hit certain value - java

I'd like to ask is it possible to stop knob moving further upon hit certain value in JScrollBar ?
For example, set the minimum and maximum value of a vertical scroll bar to 0 and 100. If the user scroll the knob till 60, he or she should not be able to move knob up further but able to move knob down.
Hence, I have simply wrote following adjust listener:
class MyAdjustmentListener2 implements AdjustmentListener
{
public void adjustmentValueChanged(AdjustmentEvent e)
{
label.setText("New Value is " + e.getValue() + " ");
if (e.getValue() < 60 )
{
vbar.setValue(60);
}
}
}
The label is a JLabel I used to monitor the adjusted value, the vbar is a vertical JScrollBar instance. Above code will force the knob jump back to value 60 if user try to move it above the value 60. This slightly different from what I want to achieve.
I have looked into the API of JScrollBar, I didn't found any straight method provided to use. Please share some hints to me here. Thank you for your time and suggestion.

Related

how to change background color back and forth eg red and green when clicked using only 1 jbutton

so what I'm trying to do is creating a button that when clicks, turns the background color to be green. once its clicked on again, it turns red. And repeat basically. So im looking for some help that show me how I can do this.
this is what I've done so far
class colorText implements ActionListener{
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("Go")) {
panel.setBackground(Color.GREEN);
}
}
}
I tried doing it by doing this but I get an error and was wondering either how to get around it or a new a way of doing it
if (e.getActionCommand() == Color.GREEN) {
panel.setBackground(Color.RED);
}
Your attempted solution doesn't work because (as we can see from the first example), e.getActionCommand() returns a String - and likely will always return "Go" when they click on your button.
What you need is some way of determining the state; telling the difference between "I should make the background red now" and "I should make the background green now". There are two ways of doing this that come to mind:
1) Check the current background colour
If the API lets you query the background colour and compare against a constant, you could check it like so:
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("Go")) {
if (panel.getBackground() == Color.RED) {
panel.setBackground(Color.GREEN);
} else { // could check for GREEN background here
panel.setBackground(Color.RED)
}
}
}
Possible downsides to this approach:
You might not be able to (reliably) read back the colour that you set. Either it's not exposed in the panel's API, or the value you get back does not equate to the Color constants for some reason (e.g. the read value has an alpha channel while the constants do not)
This only works if this method is the only way that the background gets modified. If any other code were to modify the background, you'd not have an accurate record of what your previous button press did. This is potentially a big issue as it means this code doesn't play nicely with other functionality.
2) Store a flag and flip it each time
This approach involves storing an explicit field that lets you know what to set the background to next. This could just be a boolean, like so:
private boolean greenIsNext = true
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("Go")) {
Color nextColour = greenIsNext ? Color.GREEN : Color.RED
panel.setBackground(nextColour);
// Flip the flag
greenIsNext = !greenIsNext
}
}
This is likely the cleaner way to handle this behaviour, as pressing the button will alternate between setting the background green and red regardless of what else is going on with the page.

Open new JFrame when progress bar reaches 0?

Im trying to make a java game where when the players health reaches 0 the game should end but currently when my progress bar reaches 0 nothing happens here is my code is there something wrong with it?
JProgressBar healthProgressBar = new JProgressBar();
lblHealth.setLabelFor(healthProgressBar);
healthProgressBar.setStringPainted(true);
healthProgressBar.setValue(100);
healthProgressBar.setMinimum(0);
healthProgressBar.setBounds(318, 103, 166, 20);
mainGame.add(healthProgressBar);
if(healthProgressBar.getValue() <= healthProgressBar.getMinimum())
{
frame5.setVisible(false);
frame7.setVisible(true);
}
You are actually checking it right after setting the value to 100, so it always returns false.
Instead, you can use a listener for example:
healthProgressBar.addChangeListener(e -> {
if (healthProgressBar.getValue() <= healthProgressBar.getMinimum()) {
frame5.setVisible(false);
frame7.setVisible(true);
}
});
Other way would be changing the frames where you set the value to the healthProgressBar.
You're calling this code,
if(healthProgressBar.getValue() <= healthProgressBar.getMinimum())
in the same region where you create your JProgressBar and not where the state of the JProgressBar is being changed, so it makes sense that the if block test will never be true. A solution is to call this if test where your JProgressBar is being changed. But also re-think your desire to swap JFrames. Instead the user is much better off if you would re-set a single game JFrame.
You are checking the value only once, when it is still 0

Do not change right the icon,java

i have a problem with my code. I think that my problem is easy,but i have compiled for 3 days without good results. I have three images. They are put on screen one-one each time. User choose from 4 button if image's side is up, down, right or left. Also, i want to understand if user was wrong and then i will count errors. When user make 3 errors then the game will stop. I have shown code below. Please help me if you have any good idea.
The problem is that at the first loop,run right.It goes at the first if. After that it do the loop and then it does not go to second if.
if it is more helpful,some details:
i want to make a programma that it will show to user an image.This image has 4 sides (up,down,right,left).When the image is at "up side",user has to click on up button,when the image is at "down side",user has to click on down button etc. User can do 3 errors max. At first,program show the image at right side,if user clicks on right button then i want to show the "second image" at left side.If user does not at left side,then i want to add an error(error++) and after it shows the third image at up side etc. I hope it is more helpful to understand. If you can't please let me know.
My program is at Netbeans,java.
Thank you
public void actionPerformed(ActionEvent e)
{
while(errors<3)
{
image.setIcon(createImageIcon("visual1" + e.getActionCommand() + ".PNG"));
if (k==1)
{
if(e.getSource() == right_button)
{
image.setIcon(createImageIcon("visual2" + e.getActionCommand() + ".PNG"));
}
}
else if ( k==2 )
{
if(e.getSource() == left_button )
{
image.setIcon(createImageIcon("visual3" + e.getActionCommand() + ".PNG"));
}
}
else if (k==3 )
{
if(e.getSource() == up_button)
{
System.out.print("if3");
}
}
else
{
errors++;
}
k=k+1;
}
}
You should consider calling Repaint and Invalidate, right after you update your GUI like this -
mainframe.repaint();
mainframe.invalidate();
here mainframe is your JFrame object.
A problem I see with your while loop is that it is at risk of getting stuck in an infinite loop, since the variable used as an exit criterion is only updated some of the time, in an else block. I think you should re-arrange your logic:
Get rid of that while loop as it will only cause trouble. It is useful for a linear command line program but not for an event-driven GUI program like yours.
Read in all images and create all ImageIcons in the class constructor, and store them in variables. There's no need to re-read the images multiple times (unless they're huge).
Instead of using a while loop, increment the error variable in your method above, and then write the method so that it will change behaviors depending on the value of error (depending on the state of the class).
e.g.,
// somewhere in your code create your icons
Icon rightIcon = ......;
Icon leftIcon = .....;
Icon upIcon = .....;
Icon downIcon = .....;
// elsewhere in your code
public void actionPerformed(ActionEvent e) {
if (errors >= 3) {
// notify user of error
return; // end this method
}
// check if current icon matches image
// if so, change icon
// if not increment error
}
Note that an enum Direction {UP, DOWN, LEFT, RIGHT} and a Map<Direction, Icon> could be helpful here.

Controlling the background color of a JTextField with a mouse clicked event

I'm currently working on a program of mine for personal development as a programmer and I have hit a miniature brick wall of frustration on this mouseclicked event I'm working on. When I thought up the procedure in my mind and on the white board I saw it utilizing a switch statement to get the job done. I have met with no success with this plan. I have since experimented with a few other control structures, but nothing seems to work the problem is controlling the control structure inside the mouseClicked event. I'll provide some relevant example code to try to communicate my objective. Note that I know the provided code is bad. I'm just trying to communicate an idea.
The goal is to be able to have the box start out green, then the user can click the box turn it red, click again it goes white, and one last time it goes back to green. For some reason this is beyond me at the moment. Any and all help will be greatly appreciated. Thanks in advance!
//This component allows the user to store information on current unit identifier. Maybe necessary to pass this in as an arguement to the PssGui since there is no accounting for callsigns.
//This component also needs to be updated with a mouse click event that can turn the color of the box to reflect the tooltip text.
unitId = new JTextField();
unitId.setEditable(false);
unitId.setBackground(Color.GREEN);
unitId.setHorizontalAlignment(SwingConstants.CENTER);
unitId.setToolTipText("<html>SHADE CELLS TO REFLECT CURRENT UNIT STATUS:" + "<br/>GREEN-MC" + "<br/>RED-NMC" + "<br/>WHITE-UNIT IN TRANSISTION</html>");
unitId.setText("A 4/5");
unitId.setBounds(0, 116, 79, 172);
getContentPane().add(unitId);
unitId.setColumns(10);
unitId.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
//Fill with sweet code to change the color of this box accordingly.
//use an Int and a while loop or something so that every click increments the Int
//then each int value corresponds to a color
// have a statement at the end that resets the int back to zero to keep the colors in the loop
//I.E int color = 0, mouse click happens int color = 1, now color =1 which turns the box red,
//color can never be greater than 3, when it is, we set color back to zero.
for(int i = 0; i<=3; i++){
switch (i){
case 1: unitId.setBackground(Color.GREEN);
break;
case 2: unitId.setBackground(Color.red);
break;
case 3: unitId.setBackground(Color.white);
break;
}
}//end while
//System.out.println(i);
}
});
Addendum:
I fixed my own problem. I knew it was going to be something trivial and I apologize if posting here was a waste of server resources. I was massively frustrated last night when I was trying to solve this problem. Here is the functional code. The lesson to remember here is to take a break and don't always try to force the solution.
unitId = new JTextField();
unitId.setEditable(false);
unitId.setBackground(Color.GREEN);
unitId.setHorizontalAlignment(SwingConstants.CENTER);
unitId.setToolTipText("<html>SHADE CELLS TO REFLECT CURRENT UNIT STATUS:" + "<br/>GREEN-MC" + "<br/>RED-NMC" + "<br/>WHITE-UNIT IN TRANSISTION</html>");
unitId.setText("A 4/5");
unitId.setBounds(0, 116, 79, 172);
getContentPane().add(unitId);
unitId.setColumns(10);
unitId.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
//Fill with sweet code to change the color of this box accordingly.
//use an Int and a while loop or something so that every click increments the Int
//then each int value corresponds to a color
// have a statement at the end that resets the int back to zero to keep the colors in the loop
//I.E int color = 0, mouse click happens int color = 1, now color =1 which turns the box red,
//color can never be greater than 3, when it is, we set color back to zero.
if(starter==0){
unitId.setBackground(Color.GREEN);
starter++;
}
else if(starter==1){
unitId.setBackground(Color.WHITE);
starter++;
}
else if(starter==2){
unitId.setBackground(Color.RED);
starter++;
}
else{
starter=0;
unitId.setBackground(Color.GREEN);
}
//System.out.println(i);
}
});

Linked JSliders With Maximum Combined Value

What's the best way to 'link' JSliders to put a cap on the combined value?
Imagine a fighting game where the user can specify character traits like speed, agility, endurance and accuracy. The user is given 100 points to allocate however he chooses, but the total value of all the sliders must not exceed 100. That is, the sliders should not allow such increases.
If the user has allocated 30 points each to speed, agility and endurance, then the slider for accuracy should allow a maximum of 10 points (because 30 + 30 + 30 + 10 = 100). Notwithstanding, the range of the each slider should remain unchanged (in this case, 0 to 100).
I hope this makes sense. Thanks for the help.
"nichts einfacher als das" - dachte ... (insert name :-)
Basically, all such enhanced functionality must be implemented in the model: for JSlider, that's a BoundedRangeModel. Implement/extend and enforce its value to respect the "combined" max. Something like
public static class LimitedBoundedRangeModel extends DefaultBoundedRangeModel {
BoundedRangeModel limit;
public LimitedBoundedRangeModel(BoundedRangeModel limit) {
this.limit = limit;
}
/**
* #inherited <p>
*/
#Override
public void setRangeProperties(int newValue, int newExtent, int newMin,
int newMax, boolean adjusting) {
if (limit != null) {
int combined = newValue + limit.getValue();
if (combined > newMax) {
newValue = newMax - limit.getValue();
}
}
super.setRangeProperties(newValue, newExtent, newMin, newMax, adjusting);
}
}
// use
LimitedBoundedRangeModel firstModel = new LimitedBoundedRangeModel(null);
LimitedBoundedRangeModel secondModel = new LimitedBoundedRangeModel(firstModel);
firstModel.limit= secondModel;
JSlider first = new JSlider(firstModel);
JSlider second = new JSlider(secondModel);
While simple (two dependents only) and crude (direct bidirectional coupling) and as such not really usable out in the wild, it should at least work ... but doesn't - one of those surprises which hit me from time to time ;-) The visual problem is the thumb-position:
the combined max is respected when clicking to the right of the thumb: the thumb never moves over the threshhold
when dragging, the thumb can be moved everywhere which might be expected, as the ui isn't aware of the model tweak - it knows only the "local" max
on drag-end, the thumb remains at that invalid position.. which smells like a bug as now the thumb is out-off synch with the model
The reason for this misbehaviour is that the changeListener in Handler: it doesn't recalculate its thumb position when dragging (which is okay). The subtle bug is, that the internal dragging flag is only reset after the model's adjusting property is reset, so missing the very last notification about the final value ...
Hack around is to invoke the firing of an additional changeEvent, if the adjusting flag changes from true to false
boolean invoke =
(adjusting != getValueIsAdjusting()) && !adjusting;
super.setRangeProperties(newValue, newExtent, newMin, newMax, adjusting);
if (invoke) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
fireStateChanged();
}
});
}
Create 4 sliders and some variables: the maximum total value (say, 100) and the current total (0).
When the value of any of the sliders modifies, do:
// I hope my logic isn't failing me at this point
if (slider.getValue() > (maxTotal - currentTotal))
slider.setValue(maxTotal - currentTotal);
currentTotal = slider1.getValue() + slider2.getValue()
+ slider3.getValue() + slider4.getValue();

Categories

Resources