I have a TableView and one column contains buttons. When I press the button a line is created and I drag the mouse to draw the line to another button.
The line starts and ends at the center of each button, however, I need the line to display BEHIND the buttons, yet over the table.
In Swing I would simply override the paint method of any component and write any custom graphics drawing before actually painting the button.
How can I achieve the same thing using JavaFX?
Try to make use of Node.toFront() and Node.toBack().
Related
I am trying to create something similiar like MS paint and I need a feature where I can click on the scene and immediately being able to write where I clicked. I took the the entire code example from this Anwser to solve how to switch between canvas and textarea. In other word how to switch between "drawing" and "writing" mode. So currently I can draw and write Current progress , but my problem is I want to write text where ever I click on the textarea and not at the beginning of the row.
This is how I imagine it (Goal).
So I wanted to add a handler, which can give the mouse coordinates and set the Caret to that positon:
textarea.setOnMouseClicked(event->{
textarea.positionCaret();
});
To only realise that positionCaret() only takes 1 parameter.
So I am not able to position my "Caret" to the x,y position of my mouse click.
So the question is how do I move the "Caret"/cursor to any given positon within my textarea?
Explaining Caret positioning and why it is irrelevant for your purposes
You are misunderstanding the concept of the caret position-related APIs for JavaFX text input. The APIs have nothing to do with screen coordinates. They are referring to the position of the caret with respect to the text in the text input field.
Let's say you have the following word:
happy
Caret position 0 positions the caret before the h.
Caret position 3 positions the caret in-between the two ps.
Once the caret is positioned. If somebody starts typing, the new text will be inserted at the caret.
So if you do:
setCaretPositon(3)
Then you type haphap, then the text will become:
haphaphappy
If somebody clicks in an editable text field, the JavaFX system is smart enough to handle the click by default to position the caret next to the closest letter to the click (and also handle selection and other tasks). You don't need to write any code to get the functionality.
So the caret API has nothing to do with the task you want to accomplish.
Absolute positioning for Text (or any other Node)
If you want to define an absolute position for a text input field on mouse click, then you do it in the exact same way you position any node in JavaFX, i.e. you use the node layout functions. Specifically, you set the x and y coordinates of the node. The co-ordinate system and relevant APIs are explained in the Node javadoc. To set both the x and y values at once, you call the relocate method.
Example for positioning editable text in a pane on mouse click
Here is an example, which generates a new text area and positions the top left corner of the new text area at the position a mouse was clicked.
Pane pane = new Pane();
pane.setOnMouseClicked(event -> {
if (event.getTarget() == pane) {
TextArea newTextArea = new TextArea();
newTextArea.relocate(
event.getX(),
event.getY()
);
pane.getChildren().add(
newTextArea
);
}
});
The example uses a Pane because that is a parent node which does not apply layout positioning to its children (unlike a StackPane which will overwrite any layout values you set and apply its own layout algorithm, which, by default, will center a node in its parent node).
You can see a more comprehensive example in context in the answer to:
How do I create an editable Label in javafx 2.2
That example will convert the text between a Label and TextField on click to allow the label value to be edited. You could choose to use such functionality in your paint program, or you could do it the way MS Paint does it.
How to emulate MS Paint
What MS Paint does is allow you to initially edit the text, but once you hit return to commit the edit, it snapshots the text and paints it as an image on the canvas, converting it from a node-type object to a bit on the canvas. Thereafter you can't edit the text directly anymore. If you want to do things that way you can use a combination of the node snapshot function and the graphics context drawImage function. If you do a snapshot, make sure you set the background correctly in the SnapshotParameters, so that it is transparent, that way the text background won't overwrite your drawing (or do set a background to the appropriate color, if you wanted an overwrite).
I won't provide full code for such functionality here at this time.
Styling text input
You probably want to style (using CSS) the text input field to get the look you want. The editable label example gives some hints on how to do this, but you probably want a different style for your app. Specifically, the default style for text input will have a box and background, which you may or may not want.
From the docs,
The ::add-line subcontrol can be used to style the button to add a
line. By default, the add-line subcontrol is placed in top right
corner of the Border rectangle of the widget. Depending on the
orientation the ::right-arrow or ::down-arrow. By default, the arrows
are placed in the center of the Contents rectangle of the add-line
subcontrol.
What's the mean of "style the button to add a line"? What's the appearance of a line? How is it shaped? What's the function of such a line?
AFAIK, a scroll-bar is consist of a background rectangle, two arrow buttons and a rectangle act as the handle:
the button to add a line
This is the button that adds a line in your scroll-area (in the direction of your scrollbar, horizontal or vertical), i.e. to scroll one line (down/right, the sub-line control will scroll one line up/left).
This is just the regular button with an arrow that you already identified on your screenshot. The default button and behaviour for scrollbars as we see them in most of GUIs.
This one line is actually called single step in the QAbstractSlider doc.
These stylesheet controls QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal, QScrollBar::add-page:horizontal, QScrollBar:left-arrow:horizontal etc allow to customize the look of these parts of the widget.
The other control QScrollBar::add-page: will allow you customize the widget area that scrolls not just one line but one page.
The size of a page can be defined by setPageStep(int) while the size of the one line can be defined by setSingleStep(int).
There is no button to add/sub one page-step. Instead you have to click in the empty space between the handle and the buttons to add/sub one line.
From what I tested (Qt5.10) this will be processed only if you also customize the QScrollBar as well. The example of the doc given by Scheff Customizing QScrollBar shows a full usage of what you can customize on a QScrollBar.
How do we create a Arrow graphics item which gets displayed on a graphics scene?
My requirement is that I drag and drop a QGraphicsLineItem from one scene to another. Once the Line item is dropped on a scene, a Arrow graphics Item should display perpendicular to the line item dropped on the scene. I should be able to display the Arrow Item on either side of the line. Currently I am able to drop a Line item onto the scene. I need source code for creation of an Arrow item.
Can somebody please help me with this scenario?
There are two possible options here. One is to have an image that you load into a QGraphicsPixmapItem and position and rotate it as desired.
The better method would be to create a class inherited from QGraphicsItem, and draw the arrow in its paint method, with the calls to drawLine.
When you inherit from QGraphicsItem, make sure that you overload the boundingRect() function, as well as the paint() function.
I'm trying to create a custom tab navigator that has to look like this http://www.freeimagehosting.net/uploads/b470d024c4.jpg.
Also, when there's a rollover, the borders of the arrow have to be in blue (like the label in the current tab).
For that purpose, I've created a custom component: a hbox containing a label and a canvas with 3 images inside (for the arrow tip that has to change depending on the currentState).
Then, I thought of overlapping the components in order to get the blue highlight color (ex: arrow button 3 is over arrow button 4. The image of the arrow tip in button 3 will be transparent outside the arrow, so that we can see the black color of the following button).
I'm now trying to position the components inside the canvas ... but I cannot.
After the creationComplete event, I assign the label text and I was calculating the coordonates of the component but it doesn't take into account the label width... -_-'
Any ideas?
Thanks. Regards,
BS_C3
Read up on the Flex Component LifeCycle. You should be positioning and sizing your child components in the updateDisplayList() method; not in a creationComplete handler.
You should assign the label text in either commitProperties or createChildren depending upon when you know what it is.
If you want to share some code, we may be able to hone in on the exact problem. If you run code like this:
myLabel.text = 'Blahblahblahblah';
trace(myLabel.width);
I would expect that the width has not changed to reflect the new text because the myLabel has not gone through it's own component lifecycle steps yet.
i have a window in Qt, on that i am drawing a picture. now i want to place the progressbar over it.
how can i do that?..
steps i am following to do
Create a window,
Draw picture in paint event of window
Then create QGridLayout layout, add your window
Display over it.
suppose i want to add progress bar, over a portion of picture window. how can i do that
i dont think its possible to implement in window paint event.
please assist me
Thanks
You can add the progress bar as child of your QWidget without adding it in the layout. This will draw the QProgressBar into the QWidget. Since you are not using the layout you will have to manually manage the position of the QProgressBar.
I think that just adding a progress bar widget to your grid layout should work.