- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在开发 IDE,但我遇到了以下问题:
我想创建TabPane,加载到程序中的某个位置(到VBox),然后使用一些addFile hanler添加TAB并通过code_workspace.fxml文件构建TAB内容(目前一切正常)。但我只想同步存储在同一个 FXML 文件中的元素的两个滚动条。具体来说就是ScrollPane(code_line_counter)和TextArea(code_text_area)的滚动条。
我学习了 Java 一年,所以我欢迎您给我的每一个建议。正如你所看到的,我的英语不是很好,所以我想你会从一段代码中读到很多信息:
FileManager.java
package sample;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class FileManager extends TabPane implements Initializable {
@FXML private ScrollPane code_line_counter;
@FXML private TextArea code_text_area;
@FXML private Label code_line_counter_label;
private int created_tabs;
public FileManager()
{
super();
super.setTabClosingPolicy(TabPane.TabClosingPolicy.ALL_TABS);
this.created_tabs = 0;
}
@Override
public void initialize(URL location, ResourceBundle resources)
{
code_text_area.textProperty().addListener((observable, oldValue, newValue) -> {
Matcher matcher_old_value = Pattern.compile("\n").matcher(oldValue);
Matcher matcher_new_value = Pattern.compile("\n").matcher(newValue);
int old_line_count = 0;
int new_line_count = 0;
while (matcher_old_value.find()) {
old_line_count++;
}
while (matcher_new_value.find()) {
new_line_count++;
}
if (new_line_count != old_line_count) {
code_line_counter_label.setText("1");
for (int i = 2; i < new_line_count + 2; i++)
code_line_counter_label.setText(code_line_counter_label.getText() + "\n" + i);
}
});
Platform.runLater(() -> {
ScrollBar s1 = (ScrollBar) code_line_counter.lookup(".scroll-bar:vertical");
ScrollBar s2 = (ScrollBar) code_text_area.lookup(".scroll-bar:vertical");
s2.valueProperty().bindBidirectional(s1.valueProperty());
});
}
public boolean addFile (StackPane work_space, VBox welcome_screen, NotificationManager notification_manager)
{
Tab new_tab = new Tab("Untitled " + (this.created_tabs + 1));
try {
FXMLLoader fxml_loader = new FXMLLoader(getClass().getResource("elements/code_workspace.fxml"));
new_tab.setContent(fxml_loader.load());
} catch (Exception e) {
Notification fxml_load_error = new Notification("icons/notifications/default_warning.png");
notification_manager.addNotification(fxml_load_error);
return false;
}
new_tab.setOnClosed(event -> {
if (super.getTabs().isEmpty()) {
this.created_tabs = 0;
work_space.getChildren().clear();
work_space.getChildren().add(welcome_screen);
}
});
super.getTabs().add(new_tab);
super.getSelectionModel().select(new_tab);
this.created_tabs++;
return true;
}
}
code_workspace.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.net.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<VBox xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.FileManager">
<children>
<HBox minHeight="-Infinity" styleClass="search-bar" VBox.vgrow="NEVER" />
<HBox VBox.vgrow="ALWAYS">
<children>
<ScrollPane id="code_line_counter" fx:id="code_line_counter" fitToWidth="true" focusTraversable="false" hbarPolicy="NEVER" minWidth="-Infinity" vbarPolicy="NEVER" HBox.hgrow="NEVER">
<content>
<Label fx:id="code_line_counter_label" alignment="TOP_LEFT" focusTraversable="false" nodeOrientation="RIGHT_TO_LEFT" text="1" />
</content>
</ScrollPane>
<TextArea fx:id="code_text_area" focusTraversable="false" promptText="Let's code!" HBox.hgrow="ALWAYS" />
</children>
</HBox>
</children>
<stylesheets>
<URL value="@../styles/ezies_theme.css" />
<URL value="@../styles/sunis_styles.css" />
</stylesheets>
</VBox>
我尝试了很多移动该代码部分的操作:
ScrollBar s1 = (ScrollBar) code_line_counter.lookup(".scroll-bar:vertical");
ScrollBar s2 = (ScrollBar) code_text_area.lookup(".scroll-bar:vertical");
s2.valueProperty().bindBidirectional(s1.valueProperty());
但没有什么可以帮助我。我还尝试删除 Platform.runLater(() -> {});
,但它也没有帮助。
各位,请问这个问题的正确解决方案是什么?
*添加:有一个非常有趣的行为 - 当我添加第一个选项卡时,它正常运行,但是当我将第二个或更多选项卡添加到程序集合中时,大约 70% 的情况下出现以下异常:
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at sample.FileManager.lambda$initialize$1(FileManager.java:75)
at sample.FileManager$$Lambda$294/1491808102.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$null$170(PlatformImpl.java:295)
at com.sun.javafx.application.PlatformImpl$$Lambda$50/1472939626.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$171(PlatformImpl.java:294)
at com.sun.javafx.application.PlatformImpl$$Lambda$49/1870453520.run(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$145(WinApplication.java:101)
at com.sun.glass.ui.win.WinApplication$$Lambda$38/123208387.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
最佳答案
查找(这实际上是访问文本区域中滚动条的唯一方法)仅在场景图中渲染该节点后才在该节点上工作(基本上,需要首先将 CSS 样式应用于该节点) 。因此,在 Controller 的 initialize()
方法中使用它们很棘手,因为该方法必须在 FXML 根返回给 FXMLLoader.load()
方法的调用者之前执行(因此在将其添加到场景图中之前)。
我认为发生的情况是 Platform.runLater(...)
在启动时成功,因为场景尚未渲染,因此 Platform .runLater(...)
在挂起的 UI 处理(包括渲染第一个场景)之后安排可运行的任务。在以后的调用中,它可能仅取决于当前帧渲染周期内何时执行此操作(因此它看起来有些随机)。
对于您的特定用例(显示行号),我建议您查看使用第三方库 RichTextFX托马斯·米库拉。
要更普遍地做到这一点是相当棘手的。确保在执行代码之前渲染一帧(或两帧)的最安全方法是使用 AnimationTimer
。这个类的 handle()
方法在每次渲染帧时都会执行一次,并且在运行时执行。所以基本的想法是计算帧数,一旦渲染了 1 个(或 2 个,如果你想真正安全的话)帧,然后进行查找(并停止动画计时器,因为不再需要它)。这有点像黑客(但是,一般来说使用查找也有点像黑客)。
这是一个作为单个类的示例(您可以对 FXML 和 Controller 使用相同的想法,为了简单起见,我这样做了):
import static java.util.stream.Collectors.toList;
import java.util.Random;
import java.util.stream.IntStream;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollBar;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;
public class SynchronizedTextAreaScrolling extends Application {
private static final Random RNG = new Random();
@Override
public void start(Stage primaryStage) {
TabPane tabs = new TabPane();
Tab tab = new Tab("Tab 1");
tab.setContent(createTextAreas());
tabs.getTabs().add(tab);
Button addTab = new Button("New");
addTab.setOnAction(e -> {
Tab newTab = new Tab("Tab "+(tabs.getTabs().size()+1));
newTab.setContent(createTextAreas());
tabs.getTabs().add(newTab);
tabs.getSelectionModel().select(newTab);
});
BorderPane root = new BorderPane(tabs, null, null, addTab, null);
primaryStage.setScene(new Scene(root, 600, 400));
primaryStage.show();
}
private HBox createTextAreas() {
TextArea lineNumbers = new TextArea();
int numLines = RNG.nextInt(20) + 20 ;
lineNumbers.setText(String.join("\n", IntStream.rangeClosed(1, numLines).mapToObj(Integer::toString).collect(toList())));
TextArea text = new TextArea();
text.setText(String.join("\n", IntStream.rangeClosed(1, numLines).mapToObj(i -> "Line "+i).collect(toList())));
lineNumbers.setMinWidth(40);
lineNumbers.setPrefWidth(60);
HBox.setHgrow(lineNumbers, Priority.NEVER);
HBox.setHgrow(text, Priority.ALWAYS);
// An AnimationTimer, whose handle(...) method will be invoked once
// on each frame pulse (i.e. each rendering of the scene graph)
AnimationTimer timer = new AnimationTimer() {
// count number of frames rendered since the timer was started:
private int frameCount = 0 ;
@Override
public void handle(long now) {
frameCount++ ;
// wait for the second frame. This should ensure that
// the text areas have been rendered to the scene and so
// they have had CSS applied. This allows us to use
// lookups on them
if (frameCount >= 2) {
ScrollBar sb1 = (ScrollBar) lineNumbers.lookup(".scroll-bar:vertical");
ScrollBar sb2 = (ScrollBar) text.lookup(".scroll-bar:vertical");
sb1.valueProperty().bindBidirectional(sb2.valueProperty());
// this animation timer is no longer needed, so stop it:
stop();
}
}
};
timer.start();
return new HBox(lineNumbers, text);
}
public static void main(String[] args) {
launch(args);
}
}
不过,对于这种特定用途,我会再次查看 RichTextFX .
关于JavaFX - 如何同步 FXML 文件中声明的两个元素的滚动条,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30357217/
我需要将文本放在 中在一个 Div 中,在另一个 Div 中,在另一个 Div 中。所以这是它的样子: #document Change PIN
奇怪的事情发生了。 我有一个基本的 html 代码。 html,头部, body 。(因为我收到了一些反对票,这里是完整的代码) 这是我的CSS: html { backgroun
我正在尝试将 Assets 中的一组图像加载到 UICollectionview 中存在的 ImageView 中,但每当我运行应用程序时它都会显示错误。而且也没有显示图像。 我在ViewDidLoa
我需要根据带参数的 perl 脚本的输出更改一些环境变量。在 tcsh 中,我可以使用别名命令来评估 perl 脚本的输出。 tcsh: alias setsdk 'eval `/localhome/
我使用 Windows 身份验证创建了一个新的 Blazor(服务器端)应用程序,并使用 IIS Express 运行它。它将显示一条消息“Hello Domain\User!”来自右上方的以下 Ra
这是我的方法 void login(Event event);我想知道 Kotlin 中应该如何 最佳答案 在 Kotlin 中通配符运算符是 * 。它指示编译器它是未知的,但一旦知道,就不会有其他类
看下面的代码 for story in book if story.title.length < 140 - var story
我正在尝试用 C 语言学习字符串处理。我写了一个程序,它存储了一些音乐轨道,并帮助用户检查他/她想到的歌曲是否存在于存储的轨道中。这是通过要求用户输入一串字符来完成的。然后程序使用 strstr()
我正在学习 sscanf 并遇到如下格式字符串: sscanf("%[^:]:%[^*=]%*[*=]%n",a,b,&c); 我理解 %[^:] 部分意味着扫描直到遇到 ':' 并将其分配给 a。:
def char_check(x,y): if (str(x) in y or x.find(y) > -1) or (str(y) in x or y.find(x) > -1):
我有一种情况,我想将文本文件中的现有行包含到一个新 block 中。 line 1 line 2 line in block line 3 line 4 应该变成 line 1 line 2 line
我有一个新项目,我正在尝试设置 Django 调试工具栏。首先,我尝试了快速设置,它只涉及将 'debug_toolbar' 添加到我的已安装应用程序列表中。有了这个,当我转到我的根 URL 时,调试
在 Matlab 中,如果我有一个函数 f,例如签名是 f(a,b,c),我可以创建一个只有一个变量 b 的函数,它将使用固定的 a=a1 和 c=c1 调用 f: g = @(b) f(a1, b,
我不明白为什么 ForEach 中的元素之间有多余的垂直间距在 VStack 里面在 ScrollView 里面使用 GeometryReader 时渲染自定义水平分隔线。 Scrol
我想知道,是否有关于何时使用 session 和 cookie 的指南或最佳实践? 什么应该和什么不应该存储在其中?谢谢! 最佳答案 这些文档很好地了解了 session cookie 的安全问题以及
我在 scipy/numpy 中有一个 Nx3 矩阵,我想用它制作一个 3 维条形图,其中 X 轴和 Y 轴由矩阵的第一列和第二列的值、高度确定每个条形的 是矩阵中的第三列,条形的数量由 N 确定。
假设我用两种不同的方式初始化信号量 sem_init(&randomsem,0,1) sem_init(&randomsem,0,0) 现在, sem_wait(&randomsem) 在这两种情况下
我怀疑该值如何存储在“WORD”中,因为 PStr 包含实际输出。? 既然Pstr中存储的是小写到大写的字母,那么在printf中如何将其给出为“WORD”。有人可以吗?解释一下? #include
我有一个 3x3 数组: var my_array = [[0,1,2], [3,4,5], [6,7,8]]; 并想获得它的第一个 2
我意识到您可以使用如下方式轻松检查焦点: var hasFocus = true; $(window).blur(function(){ hasFocus = false; }); $(win
我是一名优秀的程序员,十分优秀!