Layouting custom buttons - java

I am trying to create buttons shaped as in the following picture:
This works pretty well by doing the following:
class ArrowButton extends Composite {
ArrowButton(Composite parent, int style) {
[...]
setRegion(customRegion);
}
}
addStuff(Composite parent) {
ArrowButton b = new ArrowButton(parent, SWT.NONE);
b.setBounds(x, y, width, height);
}
However, I want to use a layout manager to layout these buttons. Ideally, the buttons are layouted on a standard size, after which they can still paint outside of this region.
Is this at all possible? How can I do this?

Layout managers have two functions: calculating the size of the composite that they are applied to and setting the bounds of the composite's children. Given the relative simplicity of your requirements (line up buttons horizontally) I'd say that you're better off doing the layout yourself (rather than trying to hack an existing implementation). You can always put your code into a delegate behind the Layout interface, if that feels better.

Related

Increase the thickness of the border of the focused area in swing

I have a problem with Java Swing and the LAF.
I am using JGoodies and I tried to increase the thickness of the border of the focused area. I tried it via the UIDefault but there is no such option. example of the Border Can you give me a hint how to set the border?
I saw this post: Change the color of the Java Swing Component Focus indicator but there is no solution to my problem.
example
This style depends on the L&F, if it supports the Table.border propriety or the Table.scrollPaneBorder.
In some cases, this property Table.scrollPaneBorder is enough but there aren't rules to have the table wrapped inside the scroll pane wrap table. In other words, you can have a table without a scroll panel.
if you have a table without scroll panel, the problem can be resolve from LookAndFeel, if your actual L&f doesn't have this support, the solutions are multiple, such as:
Use another l&f. such as Material-ui-swing, the table.border is under the developing branch, you can compile the source.
Develop a personal TableUI to set the border inside the UI such as the point one
you can wrapper your table inside a scroll pane, but it should respect the L&f rules.
1. Implement the Table UI. (from material-ui-swing)
insert a Border inside the propriety Table.border, such as:
UiManager.put("Table.border", new BorderUIResources(YOUR_BORDER));
You need to wrap the border inside the BorderUIResource because, if you implement the switch L6f inside your APP, Swing doesn't remove the propriety without the UIResource interface.
public class MaterialTableUI extends BasicTableUI {
public static ComponentUI createUI (JComponent c) {
return new MaterialTableUI();
}
#Override
public void installUI (JComponent c) {
super.installUI (c);
table.setBorder(UIManager.getBorder("Table.border"));
}
}
This answer makes an overview of all possible solutions that exist if the table is unwrapped from the Scroll Pane. In fact the propriety Table.scrollPaneBorder should be work fine
Example with material-ui-swing
set border
UIManager.put("Table.border", BorderFactory.createLineBorder(MaterialColors.COSMO_BLACK, 5));

How can SWT layout resize (grow/shrink) based on content

I have an explorer in my RCP application to which I added an inner composite with a RowLayout to show various category items. When the width of the explorer is resized I want the category items to wrap to new rows and expand the size of their parent composite.
If I initialize my inner composite with defaults, nothing happens, not even wrapping. If I set it to grab vertical space, it takes half the space, leaving the other half for the tree, which is ugly and not what is wanted. If I set hints, I does wrap but the size of its composite never changes, thus hiding the next rows. I tried adding a resize event listener and resizing my inner composite. That allows me to resize it and show all the rows, but it then covers up and hide part of the tree. I tried to do a setLocation and setSize for the tree itself to move/resize it accordingly but to no avail, it doesn't change.
How can this be made to work. What am I missing. Isn't there a simple way to ask for a layout that will use the minimum required height and no more but adjust if needed?
Thanks for your help.
Here the code:
innerComposite = new Composite(parent, SWT.NONE);
innerComposite.addListener(SWT.Resize, listenerComp);
GridDataFactory.fillDefaults().hint(10, 30).applyTo(innerComposite);
GridLayoutFactory.fillDefaults().applyTo(innerComposite);
Listener listenerComp = new Listener() {
public void handleEvent(Event event) {
Widget widget = event.widget;
Composite comp = (Composite)widget;
Composite parent = comp.getParent();
Point parentSize = parent.getSize();
Point size = comp.computeSize(parentSize.x, SWT.DEFAULT);
comp.setSize(size);
}
}
And here's an image:
And after resize (noticing that the 1st row of the tree is covered up):
When you are using Layouts calling setSize (or setBounds) will mess up the layout that has been setup.
Instead you should call layout(true) (or even layout(true, true) on the Composite which owns both the Tree and your innerComposite.

Dynamically resize images linked to JLabels in a GridLayout layoutmanager

Current implementation layout:
((EDIT: added
Code: ))
private JPanel panelCenter;
private List<BufferedImage> listCreatedImages;
public ChooseCircuitPanel(List<BufferedImage> listCreatedImages) {
this.listCreatedImages = listCreatedImages;
initiate();
}
private void initiate() {
setLayout(new BorderLayout(50, 50));
panelCenter = new JPanel();
LayoutManager theLayout = new GridLayout(0, 3, 0, 0);
panelCenter.setLayout(theLayout);
panelCenter.setBorder(BorderFactory.createLineBorder(Color.BLACK));
for (BufferedImage bufferedImage : listCreatedImages) {
ImageIcon theImage = new ImageIcon(bufferedImage);
JLabel lblForImage = new JLabel(theImage);
lblForImage.setBorder(BorderFactory.createLineBorder(Color.BLACK));
panelCenter.add(lblForImage);
}
this.add(panelCenter, BorderLayout.CENTER);
}
Situation:
We want to display a race circuit here. A circuit should be displayed by placing standards tiles next to each other. It should be possible to resize the window, and with that, the circuit tiles should also resize.
((EDIT: bit more info: The race circuit data is stored on a server and the desktop application has to translate the data to a visual thing, by placing some standard tiles in the right order. ))
((EDIT: we are not allowed to use any external library. It should be doable by only using Java Swing code.))
I thought about placing the images in a JLabel and placing these JLabels in a panel with GridLayout as layout manager.
Using a GridLayout - I thought - it should be rather easy to get to a solution:
the components in the GridLayout (= JLabels) already scale and do exactly what I want.
Now, it would only be a matter of finding a way to resize the images so they fill the JLabels.
As you can see: right now, the images have a fixed size and don't scale at all.
I browsed a bit and saw lots of solutions that boil down to using Graphics2D and super.paintComponent, etc.
But most of these solutions had nothing to do with a GridLayout.
So conclusive question:
Is there an easier solution aside from using Graphics2D, etc. knowing that I use a GridLayout?
If not, I will of course use Graphics2D, etc. but I'm now just exploring my options. :)
((EDIT: SOLVED The tiles now neatly fit on each other. Don't mind the misalignments, that's our fault.))
There are no Swing components that do what you want so you will need to write your own code.
The easiest approach would be to use Darryl's Stretch Icon on your JLabel.
Or another approach is to create your own custom component that dynamically scales the image as it is painted. Something like the Background Panel which has code that allows you to scale or tile an image.
Given the nature of the view, I would recommend abandoning images altogether and instead implement the rendering in an Icon. Presuming you can make an icon scale with the label.

Can I get multiple rows in JPanel with FlowLayout

I need solution similar to GridLayout but without resizing components in JPanel.
Everything works great with JFrame, but I need to put those components into JPanel instead JFrame.
I've seen two approaches that may suit your requirement:
Nest each component in a JPanel having FlowLayout, which respects the component's preferred size, as shown here.
Use the HORIZONTAL_WRAP or VERTICAL_WRAP orientation of JList, as shown here.
The following link might help you to choose the most appropriate layout for your needs. Its the Java Tutorial called "A Visual Guide to Layout Manager", which shows nice pictures of each layout and what they look like...
http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
Otherwise, if you say GridLayout is similar to what you need, you could always write your own MyGridLayout class (that extends GridLayout) and overwrite the method that does the autoresizing.
I stumbled upon this question myself and even though I think using z JList might be a good solution, there's an even simpler way of doing it with a customized FLowLayout, called WrapLayout, available here: https://tips4java.wordpress.com/2008/11/06/wrap-layout/
I ended up using it in my project and it works very well. The only issue I run into is when I set my window to the full screen mode the layout did not update correctly. I used a simple workaround, which was this:
//int targetWidth = target.getSize().width;
int targetWidth = target.getParent().getSize().width; // FIXME: this is a hack for getting the correct size when switching between full screen modes on Mac
With that small hack it works perfectly.
Just Override preferredLayoutSize() in flowlayout and set Maximum size to it. set Alignment as LEADING and set it to your JPanel. You'll get what you want
private FlowLayout getFlowLayout(int maximumSize)
{
if (flowLayout == null)
{
flowLayout = new FlowLayout()
{
#Override
public Dimension preferredLayoutSize(Container target)
{
Dimension dimension = super.preferredLayoutSize(target);
dimension.width = Math.min(maximumSize, dimension.width);
return dimension;
}
};
flowLayout.setAlignment(FlowLayout.LEADING);
}
return flowLayout;
}

Top alignment for FlowLayout

I'm using a FlowLayout JPanel. The panel looks ugly when child component heights are different. I'm looking for a solution to make them top-align (similar to valign="top" with table cells in HTML).
I realize this question was asked over a year ago, but like me, I thought many would stumble across this forum post and be left attempting to make a workaround like that one suggested in the bug report (failed to work for me just fyi).
Either way there is a better answer since JDK 1.6. Flowlayout has the following method:
public void setAlignOnBaseline(boolean alignOnBaseline)
If you use this method on your flowlayout and set it to true, then when flowlayout lays out the components it will check each component's baseline and align the component along this baseline.
But that's not all you need to do.
The component in question must override the following two methods in this way:
#Override
public Component.BaselineResizeBehavior getBaselineResizeBehavior() {
return Component.BaselineResizeBehavior.CONSTANT_ASCENT;
}
#Override
public int getBaseline(int width, int height) {
return 0;
}
They are methods in JComponent and layouts and layoutmanagers use these methods to determine how to layout the component.
If you take the steps mentioned above all the components will align themselves along the top of each row. Of course if you just want to use a component like JButton you will obviously have to extend it in order to achieve your desired goal... but it's not as much work as overriding layoutcontainer with a workaround that you have to debug. At least I think so.
Good luck,
-Asaf
Someone else has wished for this, in the form of a bug-report (which also lists a workaround).
Have a look at
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4295966
You should be able to use a BoxLayout. It supports vertical alignment. The only problem is you need to manually insert horizontal strut components.
Or you could try using the Relative Layout. In your case you would use:
RelativeLayout rl = new RelativeLayout(RelativeLayout.X_AXIS, 5);
rl.setBorderGap(5);
rl.setAlignment(RelativeLayout.LEADING);
JPanel panel = new JPanel( rl );
panel.add(...);

Categories

Resources