How to repaint on resize of a custom JSlider - java

Easy Java question here. I have made a custom JSlider which paints squares at the last location the user has moved the slider to. We override paintcomponent and draw the squares relative to the size of the slider. Everything works good when you use the slider properly. Problems happen though when you resize the frame. The slider grows bigger, and the slider adjuster moves with it, but our squares that we placed don't move relative to the slider. Which function should we use from JSlider to repaint when we resize the frame?
I am trying to keep the JSlider code separate from the frame code, so we want the user to be able to use our custom JSlider and not be trying to handle this resizing feature themselves. Any help on which method we should use for this?
Thanks.

You can add a ComponentListener to your slider that repaints it on componentResized.
slider.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
e.getComponent().repaint();
}
}

Related

Can you make the background of a JScrollBar transparent?

I have a series of column labels that scrolls independently from the data that is displayed in a matrix below. I can make the whole scrollbar transparent except on hover. The labels are right up against the data, which I like, however, upon hover, unless I shift the vertical scroll (which I'd rather not do), the scrollbar obscures the beginning of all the labels.
I would like to set the background of the scrollbar as transparent so that only the "grabber" (or whatever it's called) is the only thing that is drawn. (It will obscure the beginning of the labels it is over, but would be a lot less so.)
Is there any way to do that? Here is what I tried:
Color bg = new Color(255,255,255,0);
colLabelScroll.setBackground(bg);
This does not seem to make the background of the scrollbar transparent.
What I'm shooting for is like how the iPhone's scrollbar grabber hovers over info in some apps. Is that even possible with JScrollBars?
Transparent JScrollBar can do it, but consider this: if column labels are related to the data and you can scroll them independently, beginner users may not understand what is going on and associate column labels with whatever is visually aligned beneath it. Either you will need some sort of visual indicator that makes it clear that the labels are disconnected from the data, or you should change the way labels are scrolled that never leaves them statically in 1 place.
Here's how I ended up making the relationship between the labels and the data clearer:
Instead of allowing the user to independently and intentionally scroll the labels, I decided to control the label scroll position via mouse hover. This eliminates the need for the obtrusive scrollbar.
I created a scroll-bar-like indicator that shows the portion of the data the labels represent.
I highlighted the currently hovered label that corresponds to the data below it, i.e. the only label that is ever correctly aligned with the data is the one that is under (or directly above) the cursor.
When the mouse is not hovered over (or dragging from) the column labels, do not display any labels. This helps prevent invalid label/data associations by the user.
A few nuanced notes: Implementing your own scrollbar-like indicator is somewhat involved, especially if your labels are painted and then rotated, because the paint position of 0 is at the bottom of the pane, yet the vertical scroll position of the pane is at the top. You will have to track the vertical scroll position to be able to recover it again when the cursor returns since you are blanking the labels on mouse out.
When developing a plugin for IntelliJ, I accomplished it with:
scrollPane.getVerticalScrollBar().setUI(ButtonlessScrollBarUI.createTransparent());
It takes advantage of the the:
ButtonlessScrollBarUI.createTransparent()
method, which is an IntelliJ specific method. However, if you can find a ScrollBarUI which has a transparent background, you can use the same trick.
Since I got a bit lost myself at first after reading #hepcat72's answer I'm posting a little explanation about the BasicScrollBarUI class:
JScrollBar scrollbar = scrollPaneConversation.getVerticalScrollBar();
scrollbar.setUI(new BasicScrollBarUI(){
// This function returns a JButton to be used as the increase button
// You could create your own customized button or return an empty(invisible) button
#Override
protected JButton createIncreaseButton(int orientation){
}
// Same as above for decrease button
#Override
protected JButton createDecreaseButton(int orientation){
}
// This function paints the "track" a.k.a the background of the scrollbar
// If you want no background just return from this function without doing anything
// If you want a custom background you can paint the 'Graphics g' object as you like
#Override
protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds)
{
}
// This function paints the "thumb" a.k.a the thingy that you drag up and down
// You can override this function to paint it as you like
#Override
protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds)
{
}
});
Refer to the Transparent JScrollBar link posted by #hepcat72 for hints about what to do exactly in these functions.

How to get image pixel coordinates in java, by pointing mouse to a specific point on image?

I have a java code in which I need to open an image in a frame and display pixel's coordinates by moving mouse over that pixel, just like MS Paint displays. Is it possible in java? If yes, which GUI component is to be used?
Yes, its possible. you can try this code.
public void mouseClicked(MouseEvent e) {
PointerInfo a = MouseInfo.getPointerInfo();
Point point = new Point(a.getLocation());
SwingUtilities.convertPointFromScreen(point, e.getComponent());
x=(int) point.getX();
y=(int) point.getY();
}
this is Get Mouse Position pixel coordinates relative to JFrame.
as this you can do it for jLable etc.
Is it possible in java?
Yes...
If yes, which GUI component is to be used?
Pretty much anything that extends Component, but conventionally, JComponent or JPanel if you want to paint the image yourself or JLabel if you'd just prefer to display the image without a lot of fuss
Take a look at How to Use Labels and How to Write a Mouse Listener for starters...
You should also consider taking a look at Creating a GUI With JFC/Swing and Reading/Loading an Image for some other ideas/help

Using ComponentAdapter to determine when Frame Resize is finished

I'm using a simple ComponentAdapter to do something when the main JFrame window it's added to is resized. It's picking up the events without issue however I only want to act once a user has finished the resize. The componentResized() method fires multiple events for every pixel change of the resize and I don't want that as I need to scale an image when the window is resized and when it's done for every pixel it creates a huge lag.
I tried using a MouseListener on the frame to detect mouse up and down events to set a boolean as to whether it was being currently resized or not, but the events were never being triggered.
This is the simple ComponentAdapter:
private class ResizeListener extends ComponentAdapter {
public void componentResized(ComponentEvent e) {
onResize();
}
}
And it is added to the frame in the constructor using this.addComponentListener(new ResizeListener()); The class is extending JFrame so it should be added to the frame. I tried using getContentPane().addComponentListener(new ResizeListener()); but that didn't make any difference.
Any advice on a simple or effective way of only running the componentResized() method when the window is actually finished resizing would be appreciated.
Goal
I'm implementing a PDF reader which at the moment converts the page being viewed into a BufferedImage. When the user resizes the window I need to appropriately scale the image which means I can't let layout managers look after that for me. The number of componentResized events creates a huge lag as the image is being resized for every position along the user's resize path so I need to do it once the resize is finished.
Toolkit.getDefaultToolkit().setDynamicLayout(false);
This will affect all windows in the application, so if you only need this feature for a specific frame you may also want to add a WindowListener to the frame and then handle the windowActivated/windowDeactivated events to set this property.

Resize code does not correspond with mouse movement

I have some code to resize a chatpanel dynamically, but it does not move according to the mouse. What happens is the mouse moves at a faster rate than the panel gets resized. For example, how I want it to be, is in any application, when you click on the border between two windows, and drag it, the mouse stays along with the piece you are clicking on, and currently this is not happening. here is my code. please let me know if you need more
public void mouseDragged(MouseEvent e) {
if(getCursor().getType() == Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR).getType()) {
owner.adjust((int)MouseInfo.getPointerInfo().getLocation().getY());
System.out.println("vertpanel: "+(int)MouseInfo.getPointerInfo().getLocation().getY());
}
}
public void adjust(int adjustment) {
int height = this.getHeight();
System.out.println((((double)(adjustment))/height)+":"+(((double)(height-adjustment))/height));
output.setHeightPercent((((double)(adjustment))/height));
output.componentResized(new ComponentEvent(this, 1));
input.setHeightPercent((((double)(height-adjustment))/height));
input.componentResized(new ComponentEvent(this, 2));
}
there is one main panel, a chatpanel, and within it, there are two smaller panels, a chat input and a chat output
Can't tell exactly what you are doing based on your code.
I would suggest that you should NOT be manually setting the dimensions of the output and input coponents. You should let the layout manager determine how to resize each component as the parent container is resized.
So in your resize code you would need to invoke revalidate() on the parent container as it is resized.
Check out Resizing Components. You should be able to use the ComponentResizer class as long as you use setAutoLayout(true).

JScrollPane with transparent background and content

In my app, I show a popup dialog to show a large list of cards. I display them as images in many JLabel components in a JPanel subclass. I then put that object in a JScrollPane to allow for horizontal scrolling through the cards.
I want the unused space to be transparent with a dark background to show that what's behind it is disabled. I used setBackground(new Color(50, 50, 50, 200)) to achieve the look I want, but the content behind it does not redraw, so I get artifacting.
Here's what it looks like:
How would I go about fixing this? How do I get the content behind it to redraw when I scroll?
Thanks in advance.
Taking the window out of the equation for the momement.
The JScrollPane contains a JViewport which then contains you content. So you need to set your content pane to transparent, the viewport to transparent and then the scroll pane to transparent.
You can achieve this by using setOpaque(false) on each of these containers.
This will ensure that the repaint manager will now paint through the background.
The next problem is, Swing doesn't actually support "semi-transparent" components (that is, either it's opaque or transparent).
You can implement this by overriding the paintComponent method of the main component (the one on the viewport is probably sufficient)
Try the following...might give you some relief during scrolling.
You likely also have a problem when the main frame is maximized
or restored. You will need a listener for those events and a
similar fix.
jScrollPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
#Override
public void adjustmentValueChanged(final AdjustmentEvent e) {
sevenWondersframe.repaint();
}
});
jScrollPane.getHorizontalScrollBar().addAdjustmentListener(new AdjustmentListener() {
#Override
public void adjustmentValueChanged(final AdjustmentEvent e) {
sevenWondersframe.repaint();
}
});

Categories

Resources