I am using JProgressBar to display a progress bar on my frame. The progress bar is set to indeterminate mode as i dont know when the task will end. Instead of displaying the normal progress bar a wierd orange wave is displayed.
The wave keeps moving when the task is running. After it has ended the value is set to 100 and it displays it in the form or orange blocks(which are also moving!). I am using the following code to display the progress bar
Container content = this.getContentPane();
content.setLayout(null);
prog = new JProgressBar(0, 100);
prog.setValue(0);
prog.setStringPainted(true);
Dimension preferredSize;
preferredSize=new Dimension();
preferredSize.width=300;
preferredSize.height=15;
prog.setPreferredSize(preferredSize);
content.add(prog);
Insets insets = content.getInsets();
Dimension size;
size = prog.getPreferredSize();
prog.setBounds(30+insets.left, 180+insets.top, size.width, size.height);
How do i change it back to the normal progress bar?
I didn't look deep into it, but it might be a bug of Nimbus LaF.
Anyway, in order for the orange blocks to stop moving (when its value is set to 100), you also seem to need to call:
prog.setIndeterminate(false);
If you want to "automate" this, you could subclass JProgressBar, e.g.:
prog = new JProgressBar(0, 100) {
public void setValue(int newValue) {
super.setValue(newValue);
if (newValue >= this.getMaximum()) {
this.setIndeterminate(false);
}
}
};
prog.setValue(0);
...
Related
So, I dont know if I am missing something but any way I work it or look into it I am unable to click on any buttons on the screens.
I made a dialog box with a button essentially as shown in the sample projects but when ever I try to click the button nothing happens at all.
I tried firing the onClick programmatically and it works fine, I also tested that the mouse inputs were being registered okay and they were.
I am at a total loss for any reason why this wouldnt work.
My class code is below:
public class Interactable : UICanvas
{
public void interact()
{
var skin = Skin.createDefaultSkin();
var table = stage.addElement(new Table());
table.center();
table.setFillParent(true);
table.add(talk(this.entity.name, "Stay a while and glisten", "Bye!"));
}
public Dialog talk(string title, string messageText, string closeButtonText)
{
var skin = Skin.createDefaultSkin();
var style = new WindowStyle
{
background = new PrimitiveDrawable(new Color(50, 50, 50)),
//Dims the background
stageBackground = new PrimitiveDrawable(new Color(0, 0, 0, 150))
};
var dialog = new Dialog(title, style);
dialog.getTitleLabel().getStyle().background = new PrimitiveDrawable(new Color(55, 100, 100));
dialog.pad(20, 5, 5, 5);
dialog.addText(messageText);
var exitButton = new TextButton(closeButtonText, skin);
exitButton.onClicked += butt => dialog.hide();
dialog.add(exitButton);
return dialog;
}
}
}
The interact() is called when running up to another entity and pressing "E".
Which causes everything to render properly but I can't click on the button.
Additionally:
When i try to view exitButton co-ordinates theyre always 0 no matter what although the dialog appears in the middle of the window
Monogame version: 3.7
Nez version: 0.9.2
UPDATE:
So it seems like buttons are clickable but their click box is not even nearly aligning with where the buttons are truely rendered.
UPDATE2:
It seems that the issue is that where the button is being rendered and where the actual click box is are not the same.
I have Zoomed in the camera by 2 and the camera also follows my little character around. The dialog will then appear at the X,Y in relation to the current camera view but the actual click box appears at the X,Y in terms of the TiledMap (which is not always on screen).
Not too sure how to work around this.
So! The issue I was having was I was using one renderer for the entire this (The RenderLayerRenderer.) What I have done to fix this is start another renderer (A ScreenSpaceRenderer). This allows me to use it to render UI and its XY variables do not change but are just static to the visual area.
So i ended up with two renders like so:
addRenderer(new RenderLayerRenderer(0,new int[] { (int)RenderLayerIds.First, (int)RenderLayerIds.Second, (int)RenderLayerIds.Third}));
addRenderer(new ScreenSpaceRenderer(1, new int[] { (int)RenderLayerIds.UILayer }));
Using the first for my game rendering and the bottom on just for HUD things!
When I execute the following method in my program some components change when the timer runs out. For example a jTextArea I created changes in size without any events containing a construction to change its size. It doesn't matter if I first expand the jTextArea and then start the timer or vice versa.
//Show Debug Information for given Seconds with given Text
void giveUserInformation(String input, boolean function, int duration) {
//Debug information and label visibility handling
jLabelDebug.setVisible(true);
jLabelDebug.setText(input);
//Image
if (function)
jLabelDebug.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/images/ok-icon.png")));
else
jLabelDebug.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/images/Actions-edit-delete-icon.png")));
//Show duration
if (timerShowDurationRuns) {
timerShowDuration.cancel();
timerShowDuration = new Timer();
}
timerShowDurationRuns = true;
//fadeIn();
timerShowDuration.schedule(new TimerTask() {
#Override
public void run() {
jLabelDebug.setVisible(false);
timerShowDurationRuns = false;
//fadeOut();
}
}, duration * 1000);
setCursor(Cursor.getDefaultCursor());
}
When you create the JTextArea you should use code like:
JTextArea textArea = new JTextArea(5, 30);
Now the text area will be able to determine its preferred size and will remain fixed as you add text to it.
Then when you add it to the GUI you use code like:
frame.add( new JScrollPane( textArea ) );
Now as you add more data the text area size will remain fixed, but scroll bars will appear when required.
Basically, I'm trying to make a button that has the text aligned to the left (so I'm using setHorizontalAlignment(SwingConstants.LEFT)) and the image on the right border of the button, far from the text.
I already tried setHorizontalTextAlignment(SwingConstants.LEFT), but that just makes the text go relativity to the left of the icon, which is not exactly what I want, since I needed the icon to be secluded from it.
Also, I can't make any fixed spacing because it's a series of buttons with different texts with different sizes.
I can't make any fixed spacing because it's a series of buttons with different texts with different sizes.
You can dynamically change the spacing with code like:
JButton button = new JButton("Text on left:")
{
#Override
public void doLayout()
{
super.doLayout();
int preferredWidth = getPreferredSize().width;
int actualWidth = getSize().width;
if (actualWidth != preferredWidth)
{
int gap = getIconTextGap() + actualWidth - preferredWidth;
gap = Math.max(gap, UIManager.getInt("Button.iconTextGap"));
setIconTextGap(gap);
}
}
};
button.setIcon( new ImageIcon("copy16.gif") );
button.setHorizontalTextPosition(SwingConstants.LEADING);
This is a derivative of camickr's answer to allow editing in a GUI builder as well as placing it in a dynamic layout. I also removed the UIManager.getInt("Button.iconTextGap") so the gap will shrink to 0 if necessary.
I called it a 'Justified' button in analogy with justified text alignment (stretches a paragraph to left & right by growing width of space characters).
public class JustifiedButton extends JButton {
#Override
public void doLayout() {
super.doLayout();
setIconTextGap(0);
if (getHorizontalTextPosition() != CENTER) {
int newGap = getSize().width - getMinimumSize().width;
if (newGap > 0)
setIconTextGap(newGap);
}
}
#Override
public Dimension getMinimumSize() {
Dimension minimumSize = super.getMinimumSize();
if (getHorizontalTextPosition() != CENTER)
minimumSize.width -= getIconTextGap();
return minimumSize;
}
#Override
public Dimension getPreferredSize() {
Dimension preferredSize = super.getPreferredSize();
if (getHorizontalTextPosition() != CENTER)
preferredSize.width -= getIconTextGap();
return preferredSize;
}
}
This is not exactly production-ready and needs some field-testing. If I find anything, I'll edit the code.
[edit] Now works for vertical text alignments. Also simplified a bit.
[edit2] Also manipulate getPreferredSize to play nice with scroll pane (otherwise it keeps growing and never shrinks again)
You can add a layout manager to your button.
JButton btn = new JButton();
btn.add(new JLabel(text));
btn.add(new JLabel(img));
btn.setLayout(/*best layout choice here*/);
btn.setPreferredSize(new Dimension(x,y));
btn.setMaximumSize(new Dimension(maxX, minY));
btn.setMinimumSize(new Dimension(minX, minY)); //this one is most important when it comes to layoutmanagers
Sorry I can't be much help when it comes to picking out a good layout - But this will eventually get you what you want. Maybe someone else can comment on which one to use.
I have JLabel which I would like to change its size while I resize the window. When JLabel contains String which is too big, the String should be shortened, with right part visible and adds dots on the left hand side of the String.
My JLabel is inside innerPanel which is a header in middlePanel which is added to outerPanel. So when I resize window I use listener on outerPanel in that way:
outerPanel.addComponentListener(new ComponentListener() {
#Override
public void componentResized(ComponentEvent evt) {
int width = ((JPanel) evt.getSource()).getWidth();
windowSize = width;
refresh();
}
// [...] other not used override methods
});
refresh() repaints view and creates new middlePanel where is called class which creates innerPanel where is located my JLabel:
Public class InnerPanel extends JPanel {
private int maxSize;
String string = "<VERY_LONG_STRING>";
private static final int DEFAULT_INDEND_PIXEL = 70;
public InnerPanel(int windowSize) {
maxSize = windowSize - DEFAULT_INDENT_PIXEL;
createPanel();
}
private createPanel() {
// [...] gridbag and GridBagConstraints implementation
String shortString = countString();
JLabel label = new JLabel(shortString);
add(label,gc);
}
private String countString() {
int index = 0;
boolean toBig = true;
StringBuilder sb = new StringBuilder(string);
while(toBig) {
Rectangle2d rect = // [...] code which creates rectangle around text from sb.toString()
// I have no access to repo at home but if it's important I can paste it tomorrow
if(rect.getWidth() > maxSize)
sb.deleteCharAt(0);
else
toBig = false;
}
return sb.toString();
}
}
That's works fine in general, bacause it do resize JLabel in one step when I enlarge window in width. But the problem is appear when I try to reduce the window in width. In this case componentResized() calculate width step by step (and it's called multiple times), gradually decreases width by some amount of pixels till it reach real window size. It's behave in that way even thow I change window size in one step from maximum size to 800. Whole process is so slow, that it takes around a second to fit string to window size. So it looks bit like an animation.
The problem is very rare to me, bacause width in componentResized() method is calculeted step by step only when I assign windowSize variable.
When I give windowSize fixed size like for example 500 - componentResized() is called only onces - with correct width indicated real window size (!!) - and there's no its step by step decrease!
It's look like width variable which is assigned by ((JPanel) evt.getSource()).getWidth() knows that windowSize is used to dynamically change size of JLabel component even before first call of refresh() method.
If anyone have an idea what is going on here - I will be very appreciate for help.
You may be able to adapt one of the approaches shown here to better effect. As shown here, the ellipsis is supplied by the label's UI delegate via a call to SwingUtilities2.clipString(), which appends the clipString. Rather than re-invent the label UI, use TextLayout to determine the required geometry, prepend the ellipsis, and handle the alignment in a table or list renderer, as shown here.
I would like to create something like the following in Swing:
The top part is relatively easy: I can just create a table and display it. What I'm having trouble with is the square plus and minus buttons at the bottom, which are designed to add a new item or remove the selected item respectively. In particular, I haven't been able to make the square shape because on Mac OS X and some other platforms, JButtons are rectangles with rounded corners and I can't find a way to change that. Also, I'm wanting to make sure it's a perfect square and without any space in between buttons.
How can this be accomplished in a cross-platform way on Swing?
JButtons are rectangles with rounded corners and I can't find a way to change that.
Change the Border:
button.setBorder( new LineBorder(Color.BLACK) );
Edit.
Another approach is to create your own icon from an existing button. Something like the following:
JButton button = new JButton("+");
Dimension size = button.getPreferredSize();
size.x += 6;
size.y += 6;
button.setPreferredSize(size);
Rectangle rectangle = new Rectangle(3, 3, size.x - 3, size.y - 3);
ScreenImage buttonImage = ScreenImage(button, rectangle);
ImageIcon icon = new ImageIcon(buttonImage);
JButton plus = new JButton(icon);
plus.setBorder( ... );
The above code should create an image of your button on any platform. I increased the preferred size to avoid taking an image of the border.
You will need to use the Screen Image class.
This is most easily achieved by returning a preferred size that is NxN - where N is the larger of preferred width or height.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
class SquareButton extends JButton {
SquareButton(String s) {
super(s);
}
#Override
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
int s = (int)(d.getWidth()<d.getHeight() ? d.getHeight() : d.getWidth());
return new Dimension (s,s);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
JComponent gui = new JPanel(new FlowLayout());
for (int ii=0; ii<5; ii++) {
gui.add(new SquareButton("" + ii));
}
gui.setBorder(new EmptyBorder(4, 8, 4, 8));
JFrame f = new JFrame("Square Buttons");
f.add(gui);
// Ensures JVM closes after frame(s) closed and
// all non-daemon threads are finished
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// See http://stackoverflow.com/a/7143398/418556 for demo.
f.setLocationByPlatform(true);
// ensures the frame is the minimum size it needs to be
// in order display the components within it
f.pack();
// should be done last, to avoid flickering, moving,
// resizing artifacts.
f.setVisible(true);
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(r);
}
}
You can set the size of a button using using setPreferredSize():
JButton button = new JButton("+");
button.setPreferredSize(new Dimension(10, 10));
You might be able to remove the rounded corners using:
button.setBorder(BorderFactory.createEmptyBorder());
If this does not work then you can override the paintComponent() method on JButton.
Well in order to make them square, you have 2 options: 1. Make the button hold an icon image of just a square image of a transparent image. 2. you could set the button dimensions on your own. I am not sure how to set the dimensions, but that is a an option you could choose. You can just create a JToolBar that is set on the BorderLayout.SOUTH end of the window whenever you add, and whatever buttons are added onto that, will be right next to each other. To add the buttons do this:
JButton button1 = new JButton("+");
JButton button2 = new JButton("-");
JToolBar toolbar = new JToolBar();
<JPanel,JFrame,Whatever>.add(toolbar, BorderLayout.SOUTH);
toolbar.add(button1);
toolbar.add(button2);
This will add the toolbar onto the JFrame, JPanel, or whatever you're adding it onto, and it will set it to the bottom of the screen as you see above.
Hope this helps!