I have multiline label (for example 100 lines) which text is scrolling from bottom to top, something like movie credits. I would like to blur 10% of the top and bottom portions of that label so that text which is entering and leaving is blurred. How can I achieve that? I tried to stick some elements over that positions and blur them but that did not work.
I haven't seen blurrying, but usually the text is fading. Here's an example how you could do fading: Create an overlay pane with a linear gradient that goes from background color -> transparent -> background color. Like this:
public class Main extends Application {
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage primaryStage) {
TextArea textArea = new TextArea(
"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. ");
textArea.setWrapText(true);
StackPane root = new StackPane();
Pane overlay = new Pane();
overlay.setMouseTransparent(true);
Stop[] stops = new Stop[] { new Stop(0.0, Color.WHITE), new Stop(0.25, Color.TRANSPARENT), new Stop(0.75, Color.TRANSPARENT), new Stop(1.0, Color.WHITE) };
LinearGradient linearGradient = new LinearGradient(0, 0, 0, 1, true, CycleMethod.NO_CYCLE, stops);
overlay.setBackground(new Background(new BackgroundFill(linearGradient, null, null)));
root.getChildren().addAll(textArea, overlay);
Scene scene = new Scene(root, 300, 100);
primaryStage.setScene(scene);
primaryStage.show();
}
}
If you insist on blurring, you could use the snapshot function, create a snapshot of the text, blur the image and put it on top of the text.
Related
I have a form where I need to use some conditional rendering. Basically, the form needs to change dynamically based on what the user input is. For instance, if I ask "Where did you hear about us?" and give the users some default options (e.g. "Linkedin", "Our website"..), I want that if the user selects "Other" a st.text_input appears where the user can type the answer to the question.
The problem I am facing is that:
If I use st.form (with the st.submit_form_button), what happens is that the form does not dynamically adapt to the user's input. So the text_field won't show up at all when the user ticks "Other" in the example above.
If I do not use st.form, then the form reloads every time the user clicks on any widget. This does not affect the functionality of the form, but it does make for a very bad user experience!
Any tips on how I could either include conditional rendering within st.form or just avoid the bad user experience of the form being reloaded every time the user clicks on any widget?
Any help would be appreciated!
Instead of using form, you can create the form manually and create several containers to separate the code.
import streamlit as st
########################################################
# Sidebar section
########################################################
sb = st.sidebar # defining the sidebar
sb.markdown("🛰️ **Navigation**")
page_names = ["🏠 Home", "⚙️ Other"]
page = sb.radio("", page_names, index=0)
if page == "🏠 Home":
st.subheader("Example home")
st.subheader("What is Lorem Ipsum? ?")
lorem_ipsum = "Lorem Ipsum is simply dummy text of the printing and typesetting industry"\
"Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book"
st.markdown(lorem_ipsum, unsafe_allow_html=True)
else:
other_title = '<h3 style="margin-bottom:0; padding: 0.5rem 0px 1rem;">⚙️ Other</h3>'
st.markdown(other_title, unsafe_allow_html=True)
lorem_ipsum = "Lorem Ipsum is simply dummy text of the printing and typesetting industry"\
"Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book"
st.markdown(lorem_ipsum, unsafe_allow_html=True)
container_selection = st.container()
col1_cs, col2_cs = container_selection.columns([1, 2])
with col1_cs:
slider_val = st.slider("Form slider")
see_text = st.checkbox("See text")
if see_text:
st.warning("**See text** will take more time. Are you sure ?")
other = st.checkbox("Other")
if other:
st.info("Other checkbox")
result = st.button(label="other buttom")
with col2_cs:
st.caption(" ")
if result:
ccp = st.container()
with ccp:
information_title = '<h3 style="margin-bottom:0; padding: 0.5rem 0px 1rem;">📋 Ipsum is simply dummy text </h3>'
st.markdown(information_title, unsafe_allow_html=True)
I am trying to figure out, how to create an undecorated window with its regular shadow behaivor (like for all windows when using Windows).
I read several articles but non of them really worked.
As far as I understood, I have to create the main stage with some kind of padding. This stage has to have a transparent background. The actual content needs to be placed on some kind of other node.
So I took a stackpane for my root element and placed a vbox on it. The vbox should by the actual main stage area (I colored that area in green).
But I tried to use the StageStyle to transparent, I tried to fill out the stackpane with a transparent background but non of them worked. Also the shadow doesn't work as expected (I removed the shadow experiment in my example).
private void createPopup2() {
StackPane stackePane = new StackPane();
VBox rootPane = new VBox();
rootPane.setStyle("-fx-background-color: green; -fx-border-color: black; -fx-border-width: 1px;");
stackePane.getChildren().add(rootPane);
stackePane.setPadding(new Insets(20, 20, 20, 20));
Scene scene = new Scene(stackePane);
final Stage stage = new Stage();
stage.initStyle(StageStyle.TRANSPARENT);
stage.setWidth(600);
stage.setHeight(350);
stage.setScene(scene);
stage.initModality(Modality.APPLICATION_MODAL);
stage.show();
}
I am quite confused and have no idea how to fix that.
Firstly I am not sure what type of shadow you are expecting. It will be helpful if you can provide the example for shadow you tried, so that we may know the actual issue.
Having said that, have you tired using -fx-effect on VBox.? The below code creates a shadow effect around the green box.
StackPane stackePane = new StackPane();
stackePane.setStyle("-fx-background-color:transparent");
VBox rootPane = new VBox();
rootPane.setStyle("-fx-background-color: green; -fx-border-color: black; -fx-border-width: 1px;-fx-effect: dropshadow(gaussian, rgba(0, 0, 0, .75), 20, 0.19, 0, 0);");
stackePane.getChildren().add(rootPane);
stackePane.setPadding(new Insets(20, 20, 20, 20));
Scene scene = new Scene(stackePane, Color.TRANSPARENT);
final Stage stg = new Stage();
stg.initStyle(StageStyle.TRANSPARENT);
stg.setWidth(600);
stg.setHeight(350);
stg.setScene(scene);
stg.initModality(Modality.APPLICATION_MODAL);
stg.show();
You can tweak the parameters of the drop-shadow to get your desired effect.
The doc related to parameters is as below :
I am having a problem with JavaFX 3D, the problem is as follows:
When I turn my perspective camera around, the last added box (blue box) overlaps the first added box (red box), here is a screenshot:
can anyone tell me why is this happening? And is there a way to fix it? (the boxes are literally 2 box classes with a width, height, depth, position and color)
Minimal reproducible example since somebody asked for it:
Box box1 = new Box();
Box box2 = new Box();
box1.setWidth(300);
box2.setWidth(300);
box1.setHeight(300);
box2.setHeight(300);
box1.setDepth(300);
box2.setDepth(300);
box1.setTranslateX(300);
box2.setTranslateX(300);
box1.setTranslateY(300);
box2.setTranslateX(300);
Group root = new Group();
root.getChildren().addAll(box, box2);
PerspectiveCamera cam = new PerspectiveCamera();
Scene scene = new Scene(root);
scene.setCamera(camera);
stage.setScene(scene);
stage.show();
where stage is the stage inside public void start(Stage stage), JavaFX's default run method (any class that extends Application should implement it)
You probably have to add a subscene with the depth buffer enabled. See: https://openjfx.io/javadoc/15/javafx.graphics/javafx/scene/SubScene.html#%3Cinit%3E(javafx.scene.Parent,double,double,boolean,javafx.scene.SceneAntialiasing)
Solution:
I used the following constructor:
new Scene(root, WIDTH, HEIGHT, true, SceneAntialiasing.BALANCED);
instead of:
new Scene(root);
I'm new to Qml but I wanted to give it a try to see if it's worth using it in place of the old Qt Widgets, especially because I've heard it's better for mobile devices. I'm using Qml for the GUI alongside a couple of C++ classes for the core logic.
I needed a scrollable TextArea, as in a text editor, so I found that I had to use a TextArea nested in a ScrollView, like this:
ScrollView {
...
TextArea {
...
}
}
I liked the result in my dark QML app, with a nice looking text editor and nice scroll bars on my dark background.
The problem came up when I needed to implement a scrollTo function in my code. My app is a sort of player that highlights the text and scrolls down when it reaches a 1/4 of the height. I found that I could use the flickableItem.contentY property to adjust the relative position of the text in my ScrollView, but the property wasn't there even though other answers referred to it.
I reached Qt documentation and there was no sign of it, only a contentItem property. So I tried to adjust the contentItem.y property but the result was awful. The text and the whole background were panning, covering my top toolbar.
So I searched the docs for other implementations of TextArea and found that QtQuick.Controls 1.4 had a TextArea implementation that inherited the ScrollView class. That was the solution, I thought. I switched to the older implementation and managed to make the whole thing work. Now I can scroll my TextArea programmatically through the flickableItem.contentY property, and the contentHeight vs height properties to calculate how much room I have.
The problem here is that the 1.4 version has ugly looking scrollbars, and I feel like it's kind of a hack to use the older one. Is there a reason why they dropped the flickableItem property from the ScrollView? Is there another way to do the same thing with the new Controls versions?
Here is my code:
import QtQuick 2.12
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.12
TextArea {
id: textArea
anchors.fill: parent
backgroundVisible: false
/*background: Rectangle {
anchors.fill: parent
color: "#000000"
}*/
//color: "#ffffff"
textColor: "#ffffff"
selectByKeyboard: true
selectByMouse: true
verticalScrollBarPolicy: Qt.ScrollBarAlwaysOn
function scrollToY(y) {
if ((contentHeight-y) > flickableItem.height && y > flickableItem.height/4) {
flickableItem.contentY = y - flickableItem.height/4
}
}
}
I don't know the reasoning behind implementation changes between Qt Quick Controls 1 and Qt Quick Controls 2. However, ScrollView in Qt Quick Controls 2 can be programmatically scrolled through ScrollBar.vertical.position. I wrote an example code which moves the content using a timer until it's scrolled down, when the timer stops. Note, that if the content fits to the visible area then scrollbar is disabled and timer is not started because there is no need for moving the content. You can test that by changing boolean useLongText value to false.
import QtQuick.Window 2.2
import QtQuick 2.9
import QtQuick.Controls 2.2
Window {
visible: true
width: 400
height: 400
color: "blue"
property string exampleTextShort: "Lorem Ipsum is simply dummy text of the printing and typesetting industry."
property string exampleTextLong: "Lorem Ipsum is simply dummy text of the printing and typesetting industry.
Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.
It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
"
property bool useLongText: true // Change this to test with short text too
Timer {
id: timer
running: scrollView.wholeTextSeen ? false : true
repeat: true
interval: 2000
onTriggered: {
scrollView.scrollDown()
}
}
Rectangle{
id: rect
anchors.centerIn: parent
width: parent.width*0.2;
height: parent.height*0.2;
ScrollView {
id: scrollView
anchors.fill: parent
clip: true
property bool wholeTextSeen: ScrollBar.vertical.size >= 1 ? true : false
ScrollBar.vertical.policy: ScrollBar.vertical.size >= 1 ? ScrollBar.AlwaysOff : ScrollBar.AlwaysOn
TextArea {
readOnly: true
text: useLongText ? exampleTextLong : exampleTextShort
wrapMode: Text.WordWrap
}
function scrollDown() {
if (wholeTextSeen) {
timer.running = false
} else {
var scrollVar = ScrollBar.vertical.position + ScrollBar.vertical.size
console.log("scrollVar:",scrollVar)
if (scrollVar >= 1) {
wholeTextSeen = true
} else {
var step = 0.2
step = scrollVar + step > 1 ? 1 - scrollVar : step
ScrollBar.vertical.position = ScrollBar.vertical.position + step
}
}
}
}
}
}
Example output when running the long text looks like this for me:
qml: scrollVar: 0.15625
qml: scrollVar: 0.35625
qml: scrollVar: 0.55625
qml: scrollVar: 0.7562500000000001
qml: scrollVar: 0.95625
qml: scrollVar: 1
Starting point:
GridPane with 2 Columns
each Column has a Label
Like-to-have output:
space between the labels filled by dots
So far I have only come across String solutions in which the target length of the combined String is known. But this case doesn't do it for me because I need a solution which can also works when screen size changes and therefore the space between Labels do change dynamically. Could you guys please point me to the right direction?
You could put the 2 Labels in a HBox with a Region in between them, set hgrow for the labels and the Region to NEVER and ALWAYS respectively and use a linear gradient as background for the region that draws half of it's size black and the other half transparent.
Example
// 20 px wide horizontal gradient alternating between black and transparent with immediate color switch
private static final Paint FILL = new LinearGradient(
0, 0,
10, 0,
false,
CycleMethod.REPEAT,
new Stop(0, Color.BLACK),
new Stop(0.5, Color.BLACK),
new Stop(0.5, Color.TRANSPARENT)
);
// create background for regions
private static final Background BACKGROUND = new Background(new BackgroundFill(FILL, CornerRadii.EMPTY, Insets.EMPTY));
private static void addRow(Pane parent, String s1, String s2) {
// create labels
Label label1 = new Label(s2);
Label label2 = new Label('['+s2+']');
// create filler region with "stroke width" 2
Region filler = new Region();
filler.setPrefHeight(2);
filler.setBackground(BACKGROUND);
HBox hbox = new HBox(5, label1, filler, label2);
hbox.setAlignment(Pos.CENTER);
HBox.setHgrow(label1, Priority.NEVER);
HBox.setHgrow(label2, Priority.NEVER);
HBox.setHgrow(filler, Priority.ALWAYS);
hbox.setFillHeight(false);
parent.getChildren().add(hbox);
}
#Override
public void start(Stage primaryStage) {
VBox root = new VBox();
addRow(root, "JBoss", "DOWN");
addRow(root, "GlassFish", "UP");
addRow(root, "verylongprocessname", "UP");
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
You could also use a border (top only) on the Region instead of using a background and do not set prefHeight. This would allow you to actually use dots instead of strokes, but since your picture shows strokes, I posted the background approach instead...