I have a JavaFX 2.2 TilePane with several items (children). I've added css so that on mouse hover, the scale of the item is set to 1.2. By default, the order of children defines what node is drawn first and what last. Is there a way to make hovering item be above all others, without resorting to toFront() and making it be the last item (moving it to the end). This question is similar to https://stackoverflow.com/questions/13893514/scaling-children-in-a-flowpane-makes-the-children-clip-eachother (still unanswered).
Screenshot of the issue is located at: http://vladeck.files.wordpress.com/2013/03/javafx_tilepane.png?w=640
Solution / Workaround
Use a GridPane instead of a TilePane.
When the user clicks on an item in the grid, call toFront on the item.
Sample Code
I added the following code to a calculator which is based on a grid layout which looks similar to the tiled layout in your sample screenshot. With the modified application, I experienced no overlapping of buttons of the calculator. Surprising to me, though they looked a little weird, the scaled buttons made the calculator easier to use...
button.setOnMouseEntered(new EventHandler<MouseEvent>() {
#Override public void handle(MouseEvent mouseEvent) {
button.toFront();
button.setScaleX(1.6); button.setScaleY(1.6);
}
});
button.setOnMouseExited(new EventHandler<MouseEvent>() {
#Override public void handle(MouseEvent mouseEvent) {
button.setScaleX(1); button.setScaleY(1);
}
});
Background
As you note, the overlapping issue is unresolvable in some stock Panes like TilePane. This is because the z-order as well as the relative layout position of a node are both defined by the relative position of the node in the TilePane's child list. In such Panes, you cannot change the z-order and bring it to the front without also moving the node to the last layout position in the TilePane.
A GridPane does not suffer from the same issues as a TilePane because it's child node list order only defines the z-order of it's child nodes, not the layout positioning of those child nodes.
Is there a way (a hack?) to implement my own code of retrieving the children order for drawing when JavaFX repaints TilePanel?
Yes, you could hack the TilePane code if you have the skills.
Related
I'm creating an app in which I use nested FXML nodes. They are connected to parent nodes in the parent controllers using constructs like
#FXML
private AnchorPane nestedNodeConnector;
, to which I attach the child like this:
AnchorPane child = createNestedAnchorPaneWithTableViewInside();
nestedNodeConnector.getChildren().setAll((AnchorPane)child);
The code is a bit simplified, but I hopefully explained myself enough. Now my problem is that I am trying to load (as the child node) an as-large-as-possible AnchorPane with an anchored TableView inside. However I can't get this to work as the TableView dimension never sticks to the parent node (in order to grow with the window size).
I was able to get it working without nesting the child, but I really have to load the TableView in a separate FXML file. Any suggestions? I think that my approach creates an AnchorPane "child" within an AnchorPane "nestedNodeConnector", which messes up the anchor properties.
All I had to do was anchor the child AnchorPane (to the parent AnchorPane):
AnchorPane child = createNestedAnchorPaneWithTableViewInside();
AnchorPane.setTopAnchor(child, 10.0);
AnchorPane.setBottomAnchor(child, 10.0);
AnchorPane.setLeftAnchor(child, 10.0);
AnchorPane.setRightAnchor(child, 10.0);
nestedNodeConnector.getChildren().setAll((AnchorPane)child);
I have a scroll Pane with a rectangle inside the scroll Pane.The rectangle can only move left or right . The scroll pane has a with of 800,when the windows gets to small the scrollbar becomes enabled and you can scroll. My problem is when i try to move the rectangle when the scrollbar is on , the scroll bar will also move either left or right.Is the a way to temporary disable the scroll feature when i am moving the node >
I think what you might be looking for is
public final void setPannable(boolean value)
Sets the value of the property pannable.
Property description:
Specifies whether the user should be able to pan the viewport by using the mouse. If mouse events reach the ScrollPane (that is, if mouse events are not blocked by the contained node or one of its children) then pannable is consulted to determine if the events should be used for panning.
https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/ScrollPane.html#setPannable-boolean-
I'm not sure if this works, but sounds like it.
You also could use https://docs.oracle.com/javase/8/javafx/api/javafx/scene/Node.html#onMouseClickedProperty
or a similar MouseProperty, set up a Listener and make it so that when you click on the ScrollPane, it will set https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/ScrollPane.ScrollBarPolicy.html
to NEVER
public static final ScrollPane.ScrollBarPolicy NEVER
Indicates that a scroll bar should never be shown.
then back to your original setting for ScrollPane.onMouseReleased();
Good luck!
I got the task to draw some points on a map. Wrote some code but currently every point I create via shapes will be added to the wrong position inside of my gridpane. Oh and I'm using JavaFX.
I added an imageView to the index 0,0 of my GridPane and every point is created through x and y position of the MouseEvent on the imageView.
After that I added the created point as a child of the GridPane and it's displayed at the center of the y-axis of the first grid.
Tried different things like anchorPanes and canvas but can't seem to get it working.
Code of my View:
http://pastebin.com/dCb7EN4d
Code of my Main:
http://pastebin.com/vp5tzxkG
I hope that's enough ^^'
pls help!
Greetings,
Ben
GridPane is a managed layout: it will position nodes that are added to it via the properties you set (using defaults if you don't set them). So when you add your circles to the grid pane, since you don't set any properties, it will place it in cell (0,0) and align it within that cell using default settings; i.e. it ignores the centerX and centerY properties.
What you should really do here is use a layout that does not manage the positioning of the nodes for you, such as a Pane (or possibly a Group). You can put the ImageView and the Circles in the pane, and then place the pane in the rest of your layout (in the scroll pane, I think).
The other option you have is to call setManaged(false) on the nodes you add to the GridPane in order to instruct the GridPane not to position them, though this feels like more of a workaround.
I have an HBox displaying a series of canvases. I am removing a child of a canvas and adding it to the rawChildren of the containing HBox, so I can position it, and make it appear to shift outside the bounds of the canvas.
Here is the code from the canvas:
private function onMouseOver(e:MouseEvent):void
{
(this.parent as HBox).rawChildren.addChild(dateLabel);
dateLabel.x = (this.parent as HBox).localToGlobal(new Point(this.x,0)).x - 18;
}
private function onMouseOut(e:MouseEvent):void
{
addChild(dateLabel);
dateLabel.x = 0;
}
It works, but if the containing HBox.horizontalAlign is set to "right", when I add the child back to the Canvas, the HBox stops displaying correctly and puts all the child canvases overlapping on the right. There is no issue if the HBox is aligned "left" tho.
Is this a bug? Is there a work around?
Thanks!!
Is this a bug? Is there a work around?
- John Isaacks
This isn't a bug as such, it's more that you are using a container in an unusual way.
When you use an HBox you are making a decision that all children are laid out in a linear, horizontal arrangement according to the rules of the HBox component.
Explicitly positioning a child is not what HBoxes are about - it's not in their job description.
I would recommend that you have an HBox inside a Canvas. You can add the dateLabel to the HBox when it should be laid out horizontally or move it to the Canvas when you need to set its position and make it look like it's outside the HBox.
When you use rawChildren, you simply bypass the layout mechanism.
You should use addChild or addChildAt directly on the component.
I have a QListView in Icon mode with lots of icons, so that a scrollbar appears, but the scrolling is not smooth and this IMHO confuses the user since it jumps abruptly from one point to another at each scroll. I would like to make the scrolling smooth but I didn't find anything in the docs. Is it possible?
Maybe QListView.setVerticalScrollMode(QAbstractItemView::ScrollPerPixel)
If I understand your question correctly you would like to redefine the scrolling behavior of the widget. I guess what happens is that listview is getting scrolled by the item's height whenever users hits a scroll arrow (marked as b on the image below).
For a vertical scroll bar connected to a list view, scroll arrows typically move the current position one "line" up or down, and adjust the position of the slider by a small amount. I believe line in this case it is an icon's height. You can adjust items height by installing and item delegate (setItemDelegate) and overriding its sizeHint method. Though this would not help you to solve this problem. What you could try is to create a QListView descendant and override its updateGeometries method. There you can setup the vertical scrollbar step to the value you want, I guess 1 or 2 for this task. Below is an example of the custom listview:
class TestListView : public QListView
{
Q_OBJECT
public:
explicit TestListView(QWidget *parent = 0);
protected:
virtual void updateGeometries();
};
TestListView::TestListView(QWidget *parent) :
QListView(parent)
{
//???
}
void TestListView::updateGeometries()
{
QListView::updateGeometries();
verticalScrollBar()->setSingleStep(2);
}
hope this helps, regards
I have a QlistWidget* in ui->barra_scroll and I feel very smooth with this.
QScrollBar *qsb = ui->barra_scroll->verticalScrollBar();
qsb->setSingleStep(5);