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.
Related
i am trying to accomplish the following behavior with a QML TextArea:
I want single Words in the Text to be colored differently
I want the "select"-functions to be working for automated scrolling (user interaction is disabled)
There is a stream of text in the TextArea where one Word needs to be selected(highlighted). The user is requested to input some text elsewhere and press enter to proceed (not part of the question). After that the selection jumps to the next word and the last selected word is either colored green or red. There is only a small portion of the text visible (a few lines, managed by the TextArea height – not part of the question) and i need the text to scroll if the next word is out of that visible range .. therefore the selection is quite helpful because all interaction from the user – to scroll or select or whatever – is disabled (disabling is not part of the question)
my main problem is: if i use textFormat: TextEdit.RichText i can easily color the text how i like it to be (<font color=\"green\">{}</font>) but i cannot use the "select"-functions anymore because – as i would guess – the selection works on the "plaintext" and cannot correspond to the "richtext"-selection? Anyway selectWord() etc. does not work QTextCursor::setPosition: Position '-1' out of range is the result. But if i disable the RichText i don't know how to color the text. Maybe i could live without the selection if i could detect the current word – which would be colored blue etc. – and scroll if its out of the visible area to "fake" the selection behavior, but that's just a third option.
I would really either know how to color non-Rich Text or how to select Rich Text in a TextArea.
You can use QSyntaxHighlighter to highlight the words independent of the selection. See QQuickTextDocument and How to implement rich text logic on QML TextEdit with QSyntaxHighlighter class in Qt for more details.
I am using QTextEdit to implement an editor. One of the requirements I have is to add fixed position text on top of an image.
For example:
I have an image of dimensions: 300x300. I need to add text beginning at the location (20, 20) of the image and ensure that the text does not flow beyond the width of the image.
Something like below:
I am thinking that if I can add a QGraphicView, I can add the image and position text appropriately. Is this possible? Is there a way to introduce a graphic element into a QTextedit? If not, what is the right approach?
Is there a way to introduce a graphic element into a QTextEdit? If not, what is the right approach?
You could look at this the other way and add the QTextEdit to a QGraphicsScene. The graphics scene provides a QGraphicsProxyWidget to add standard Qt widgets.
Therefore, you could create a QGraphicsScene and QGraphicsView. Add a QGraphicsPixmapItem for the image and add the QTextEdit item with a call to QGraphicsScene::addWidget, which returns a QGraphicsProxyWidget, allowing you to position, scale and resize the widget.
Alternatively, you could start with a QGraphicsItem, inherit from that and create your own object which encapsulates the image and proxy object of the QTextEdit.
There are other ways of tackling this too, but I'd probably go for the custom QGraphicsItem. It also depends on your specification, but you can add text items in a graphics scene, without the QTextEdit, though you'd probably have to implement the editing feature, if this is required.
I am trying to set the text background of the JavaFx label text as green using the following CSS
label.setStyle("-fx-background-color:rgba(85, 255, 68,0.7););
And the unhighlight using the following
label.setStyle("-fx-background-color:rgba(0,0,255,0);");
However these does not work most of the times when it has to be done back to back.
Is there any way to set the style without using CSS i.e. using JavaFx API itself. I found label.textFill(Paint p) for text color but nothing for background colour i.e. the color of the label itself.
Is there any way to set the style without using CSS i.e. using JavaFx API itself.
For some styles (such as the text fill) yes. For background colors, background images, borders, etc API methods will not be available until JavaFX 8 is released (see Public API for Region backgrounds and borders in the JavaFX issue tracker for more information - anybody can sign up for access).
these does not work most of the times when it has to be done back to back.
If you just highlight a label and then unhighlight it again without using something like a PauseTransition to give the user some time to see the highlighted label, then, from the user's perspective nothing is going to happen as all the user will see is an unhighlighted label.
Not sure of your use case, but if you only want to highlight part of the text in a label or let the user highlight the text with a mouse, then you can use a TextField with editable set to false.
Possible Workaround
If the Java 8 preview does not work for you and you are experiencing errors due do bugs in the JavaFX CSS processing, then try placing a Pane then a label inside a StackPane. Set the background color of the Pane to label.setStyle("-fx-background-color:rgba(85, 255, 68,0.7);); Bind the Pane's preferred width and height to the Label's width and height and toggle setVisible on the Pane as appropriate.
Finally I found the workarround. I had to give a PauseTransition to give the system some time between unhighlight and highlight. CSS showed effect only after the pausetransaction if the labels were already highlighted. I think it may be a bug. I will file a jira. The duration of paustransition may be as low as 1 milisecond so that there is not lag from the user's point of view.
Hi i'm trying to get a photoshop-like behaviour for my QGraphicsScene
The grid in the background should not resize with the call of scale. And I must be able to save the picture with QPixmap::grabWidget(view) but without the background grid. I can probably do it with removing the background layer just before saving the picture, but i'm not sure if its cleanest way to do it.
Any ideas ?
thx.
Question 1
The grid in the background should not resize with the call of scale.
Use the QGraphicsItem::ItemIgnoresTransformations flag.
The item ignores inherited transformations (i.e., its position is
still anchored to its parent, but the parent or view rotation, zoom or
shear transformations are ignored). This flag is useful for keeping
text label items horizontal and unscaled, so they will still be
readable if the view is transformed. When set, the item's view
geometry and scene geometry will be maintained separately.
In order to set this flag use the setFlag function when creating the grid item.
Question 2
I must be able to save the picture with QPixmap::grabWidget(view) but without the
background grid.
Call the hide function on the grid item before calling the grabWidget. After you have grabbed it you show it again by calling the show 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.