Creating custom text editing component with JavaFX - javafx

I want to create a custom text editing component. Basically I need a text with an ability to set a caret and handle key events in a custom way. Is there a way to do so in JavaFX? There are implementation specific methods on Text (which are deprecated and comments say that they should be considered private), but I can't use them.
Is it possible to do so in JavaFX?

For single-lined text, use a TextField.
For multi-lined text, use a TextArea.
For a styled text, use a HTMLEditor.
If using a TextField or TextArea, they are both subclasses of TextInputControl. The TextInputControl provides a caretPositionProperty you can use to read and modify the caret position. All scene graph objects (including TextField and TextArea) are instances of Node. A node allows you to set custom EventHandlers and event filters. You can use an event handler to override the default key processing handler of the TextInputControls so that you can implement your own handling.
If you need further customization capability which you cannot get from customizing a TextField or TextArea instance, then you could create your own TextInputControl subclass and implement the custom text editing component as you need, but I wouldn't really advise that approach due to the complexity and possible required dependency on internal JavaFX apis that you would likely end up needing.
TextField doesn't work for me because: 1. It has a border which indicates focus and which I don't know how to remove.
Here is a link to the default caspian.css stylesheet for JavaFX 2.2.
You can set the the style for TextField to remove the focus border, by setting it's :focused pseudoclass selector style to the same values as it's default selector. For example:
.text-field:focused {
-fx-background-color: -fx-shadow-highlight-color, -fx-text-box-border, -fx-control-inner-background;
-fx-background-insets: 0, 1, 2;
-fx-background-radius: 3, 2, 2;
}
Refer to the JavaFX css reference guide for information on how to use css in JavaFX.
TextField doesn't work for me because: 2. It has fixed number of columns and I need to change width dynamically.
TextField is a resizable control, if you place it in a resizing layout pane with appropriate constraints it will change it's width dynamically. The number of columns setting in TextField is a preferred column count, not a fixed column count.
Refer to the JavaFX layout documentation on further information regarding layout in JavaFX.

Related

Dynamically change QStyle at runtime?

I want to tweak the existing style at runtime, specifically QStyle::PM_ToolBarIconSize. Can this be done? As far as I can tell, you can only inherit QStyle and override pixelMetric().
Edit 1: In the specific case of QStyle::PM_ToolBarIconSize, I could use QToolBar::setIconSize, but that would set the icon size for just a single toolbar instance. I want to change the underlying style hint to affect all toolbars everywhere with one fell swoop. And QStyle::PM_ToolBarIconSize may not be the only style I want to tweak, it's just the first one I'm looking at that just so happens to have a "change this instance's icon size" function.
Edit 2: I can't just make a new style subclass because the current style is already a custom style based on style sheets. There are several styles that a user can choose from. I don't want to create a bunch of new styles just so I can tweak a couple of toolbar icon or menu height size settings.
This is the exact purpose of QProxyStyle.
Why not overriding QStyle then? Your subclass would return an icon size (via pixelMetric) which depends on a settable parameter of your QStyle.
As Qt does not have a dynamic QStyle mechanism, it is better to create a new style instance with the changed icon size, then set it to the QApplication, rather than altering the current style.

Highlighting text in JavaFx Label

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.

Changing Spark TextArea text color dynamically over a range of characters

Hoping to obtain the help of some Flex 3/4 gurus out there...
I am attempting to dynamically change the color of a subset/portion of text in a Spark TextArea control. Using the MX-based TextArea, I could leverage the mx.controls.textClasses.TextRange type and change the color directly as follows:
TextRange tr = new TextRange(theTextAreaControl, false, beginIndex, endIndex);
tr.color = somePredefindColor;
Input Parameters to TextRange constructor:
1st argument: The TextArea control that will provide access to the underlying textField property
2nd argument: Indicates the TextRange will not modify the content of the TextArea
3rd argument: The beginning index position in the TextArea text string
4th argument: The ending index position in the TextArea text string
How would I go about doing this for a Spark-based TextArea control? I am looking to dynamically change the font color for a range of text, not just the entire TextArea AND I cannot statically specify the font color. The problem I run into when trying to re-use the TextRange type is that the 1st argument is expected to provide the textField property, which is currently not on the Spark-based TextArea control. I thought about extending the Spark-based TextArea control to provide this accessor property but that seems like overkill and is probably not the best approach.
Any help would be greatly appreciated.
Thanks,
Michael
When manipulating Spark text components, you'll want to use the Text Layout Framework (TLF), which is built on top of the Flash Text Engine (FTE) that was introduced in Flash Player 10. It gives you major control over how the text is displayed (at the cost of being pretty complex.) Here's a good place to start: Using Text Layout Framework

What is the right method for modifying text content in Flex component lifecycle?

I have custom components which must adjust their text content based on space constraints. For example a component adds labels until there is no space, and then the content of the last label becomes "(x more)"
I do not have access to size of child controls before adding them. When in updateDisplayList, I make changes to the layout of the component, but for labels, lblInstance.text property fires events, which lead to updateDisplayList being called again. I know that updateDisplayList may be called more than once, but if there is a way to modify text without triggering events, that'd be really useful. For example, setActualSize method in UIComponent allows this kind of modification.
Anything similar for text controls? Or do you have best practices for laying out and managing text content, in the context of custom Flex components?
Best Regards
Seref
Use the measure() method to set your text component sizes.
You will probably have to call validateNow() on them so that they will be forced to figure out the actual textWidth and textHeight and return the actual number of lines of text in the textField if they are long enough to wrap. Investigate the TextMetrics class for more ways to measure.

Formatting AdvancedDataGrid Cells

I have a quick question about rendering the advanceddatagrid cells.
I need to programatically color the cell of the datagrid based on the conditions. Lets say, the stock quotes. If there is an increase from the previous day, I need to have the cell colored in GREEN and in RED, when there is a decrease.
Now, the important part here is, I need to do these things dynamically, which means, when the user enables the comparison/conditions, then the cells are colored. And when the user disables the comparison, then it again goes back to its default behavior.
I know I have to use renderers. But not sure, how to use it for the cells and that too dynamically. Can anyone please explain how to go for it?
Thanks
Item renderers are components used to define the appearance of a component's "items" or subcomponents. In the case of the ADG, the "items" are the individual cells. You can create a completely custom class to function as the renderer (given it implements certain required interfaces) or, in most cases, you extend an existing component. Since the default renderer for ADG cells doesn't support background colors, you have to create or extend a component that does and use that as the renderer. That is the basic premise that these tutorials, linked to in the following question, work from:
Setting background color for datagrid row in Adobe Flex
After creating an itemRenderer that supports a background color, you have two options as to where you can define your "conditions"; inside of the itemRenderer or using the ADG's styleFunction (additionally requiring that your itemRenderer defines a "background" style).
In your case, you could include both today's and yesterday's stock price values in the data sent to each cell and compare the two to determine the color used to draw the background. Again, more on that in the tutorial links provided above. In either the itemRenderer or the styleFunction, you would compare properties on the itemRenderer's/styleFunction's data object (corresponding to the row you're looking at), e.g.:
if(data.today > data.yesterday)
{
// set color or return style
}
else ...
To "toggle" custom cell colors, switch between your custom renderer and the default (colorless) renderer. In other words, set the itemRenderer property to your custom itemRenderer class when you need display the colors and set it to "null" when you want the "default behavior".

Resources