- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试使用 JavaFX 证明一个可扩展的小部件,它与 TitledPane
的不同之处在于标签周围的边框随着小部件的扩展而增长。我找到了一种方法。
但是我有一个奇怪的故障,在展开/折叠一两次后出现。
这是一个短视频的链接,问题出现在第三次和第四次扩展中:
Short Youtube Concept / Glitch Video
我已经用尽了所有可以尝试让它正常运行的东西。
代码如下,对它的古怪表示歉意,希望在我重构它之前让它工作。
class ExpansionManager {
enum LayoutState {
INITIALIZE,
ANIMATING,
IDLE,
REQUEST_ANIMATION
}
LayoutState layoutState = LayoutState.INITIALIZE;
Double fromWidth = 0.0;
Double fromHeight = 0.0;
Double stepWidth = 0.0;
Double stepHeight = 0.0;
Double toWidth = 0.0;
Double toHeight = 0.0;
}
public class ExpandableTitledList extends VBox {
private Label title = new Label();
private ListProperty<String> listItem = new SimpleListProperty<>();
private ListView listView = new ListView<>(listItem);
Timeline timeline;
WritableValue<Double> writableHeight = new WritableValue<Double>() {
@Override
public Double getValue() {
return expansionManager.stepHeight;
}
@Override
public void setValue(Double value) {
expansionManager.stepHeight = value;
requestLayout();
}
};
WritableValue<Double> writableWidth = new WritableValue<Double>() {
@Override
public Double getValue() {
return expansionManager.stepWidth;
}
@Override
public void setValue(Double value) {
expansionManager.stepWidth = value;
requestLayout();
}
};
private boolean expanded = false;
ExpansionManager expansionManager = new ExpansionManager();
// private Dimension2D contractedDimension;
// private Dimension2D expandedDimension;
public ExpandableTitledList() {
setTitle("boom");
// title.layout();
// System.out.println(title.getLayoutBounds().getWidth());
// set down right caret
listItem.setValue(FXCollections.observableArrayList("one", "two"));
Insets theInsets = new Insets(-3, -5, -3, -5);
Border theBorder = new Border(
new BorderStroke(
Color.BLACK,
BorderStrokeStyle.SOLID,
new CornerRadii(4),
new BorderWidths(2),
theInsets
)
);
// expandedDimension = new Dimension2D(200,200);
setBorder(theBorder);
getChildren().addAll(title);
title.setOnMouseClicked((event) -> {
System.out.println("mouse clicked");
if (this.expanded) contract();
else expand();
});
}
@Override
protected void layoutChildren() {
System.out.println(expansionManager.layoutState);
if (expansionManager.layoutState == ExpansionManager.LayoutState.INITIALIZE) {
super.layoutChildren();
expansionManager.layoutState = ExpansionManager.LayoutState.IDLE;
} else if (expansionManager.layoutState == ExpansionManager.LayoutState.ANIMATING) {
super.layoutChildren();
} else if (expansionManager.layoutState == ExpansionManager.LayoutState.REQUEST_ANIMATION) {
setCache(false);
listView.setCache(false);
expansionManager.layoutState = ExpansionManager.LayoutState.ANIMATING;
System.out.println("from : " + expansionManager.fromWidth + ", "+ expansionManager.fromHeight);
System.out.println("to : " + expansionManager.toWidth + ", "+ expansionManager.toHeight);
timeline = new Timeline();
timeline.getKeyFrames().addAll(
new KeyFrame(Duration.ZERO,
new KeyValue(writableHeight, expansionManager.fromHeight),
new KeyValue(writableWidth, expansionManager.fromWidth)),
new KeyFrame(Duration.millis(100),
new KeyValue(writableHeight, expansionManager.toHeight),
new KeyValue(writableWidth, expansionManager.toWidth))
);
timeline.play();
timeline.setOnFinished((done) -> {
System.out.println("done");
expansionManager.layoutState = ExpansionManager.LayoutState.IDLE;
timeline = null;
});
} else {
System.out.println("idle");
super.layoutChildren();
}
}
@Override
protected double computePrefHeight(double width) {
if (expansionManager.layoutState == ExpansionManager.LayoutState.INITIALIZE) {
expansionManager.fromHeight = super.computePrefHeight(width);
return expansionManager.fromHeight;
} else if (expansionManager.layoutState == ExpansionManager.LayoutState.ANIMATING) {
return expansionManager.stepHeight;
} else if (expansionManager.layoutState == ExpansionManager.LayoutState.REQUEST_ANIMATION) {
expansionManager.fromHeight = getHeight();
expansionManager.stepHeight = expansionManager.fromHeight;
expansionManager.toHeight = super.computePrefHeight(width);
return expansionManager.fromHeight;
} else {
return expansionManager.toHeight;
}
}
@Override
protected double computePrefWidth(double height) {
if (expansionManager.layoutState == ExpansionManager.LayoutState.INITIALIZE) {
expansionManager.fromWidth = super.computePrefWidth(height);
return expansionManager.fromWidth;
} else if (expansionManager.layoutState == ExpansionManager.LayoutState.ANIMATING) {
return expansionManager.stepWidth;
} else if (expansionManager.layoutState == ExpansionManager.LayoutState.REQUEST_ANIMATION) {
expansionManager.fromWidth = getWidth();
expansionManager.stepWidth = expansionManager.fromWidth;
expansionManager.toWidth = super.computePrefWidth(height);
return expansionManager.fromWidth;
} else {
System.out.println("BANG BANG BANG");
return expansionManager.toWidth;
}
}
// @Override
// protected double computeMinWidth(double height) {
// return computePrefWidth(height);
// }
//
// @Override
// protected double computeMinHeight(double width) {
// return computePrefHeight(width);
// }
//
// @Override
// protected double computeMaxWidth(double height) {
// return computePrefWidth(height);
// }
//
// @Override
// protected double computeMaxHeight(double width) {
// return computePrefHeight(width);
// }
private void expand() {
System.out.println(expansionManager.layoutState);
// if(contractedDimension == null)
// contractedDimension = new Dimension2D(this.getWidth(), this.getHeight());
// setPrefSize(expandedDimension.getWidth(), expandedDimension.getHeight());
expansionManager.layoutState = ExpansionManager.LayoutState.REQUEST_ANIMATION;
this.getChildren().setAll(title, listView);
expanded = true;
}
private void contract() {
// this.setPrefSize(contractedDimension.getWidth(), contractedDimension.getHeight());
expansionManager.layoutState = ExpansionManager.LayoutState.REQUEST_ANIMATION;
this.getChildren().setAll(title);
expanded = false;
}
public String getTitle() {
return title.getText();
}
public void setTitle(String title) {
this.title.setText(title);
}
}
最佳答案
我发现 ListView
是出现故障的原因。
基本上,除了第一次之外,每次将列表添加到 VBox
时,您都可以在其容器之外的非常短暂的瞬间看到完整大小的列表,然后当时间线开始时,它的大小已适当调整。
事实上,您可以在时间轴上添加延迟(例如一秒):
timeline.setDelay(Duration.millis(1000));
如果您第二次展开该框,您会在整整一秒内看到问题:
列表在 VBox
之外是可见的,因为它没有调整大小以适应它。当动画开始时,它会调整大小,问题就消失了。
那时我已经尝试了几种方法来调整列表的大小,但都没有成功。也许你可以解决它...
一个丑陋的解决方案是在每次展开框时创建一个新的列表实例:
private void expand() {
expansionManager.layoutState = ExpansionManager.LayoutState.REQUEST_ANIMATION;
// this works...
listView = new ListView<>(listItem);
this.getChildren().setAll(title,listView);
expanded = true;
}
寻找其他替代方案,我已将 disableProperty()
框绑定(bind)到时间轴,因此在扩展或收缩带标题的列表时您无法单击。
所以另一种解决方案是将列表 visibleProperty()
绑定(bind)到时间轴,但您不会看到很好的增长效果。
还有第三种解决方案,它也与动画一致:在将列表添加到框中之前将不透明度设置为 0:
private void expand() {
expansionManager.layoutState = ExpansionManager.LayoutState.REQUEST_ANIMATION;
// this will avoid seeing the unresized listView
listView.setOpacity(0);
this.getChildren().setAll(title,listView);
expanded = true;
}
并添加一个新的 KeyValue
增加列表 opacityProperty()
从 0 到 1 到时间线:
timeline.getKeyFrames().setAll(
new KeyFrame(Duration.ZERO,
new KeyValue(listView.opacityProperty(), 0),
new KeyValue(writableHeight, expansionManager.fromHeight.get()),
new KeyValue(writableWidth, expansionManager.fromWidth.get())),
new KeyFrame(Duration.millis(300),
new KeyValue(listView.opacityProperty(), 1),
new KeyValue(writableHeight, expansionManager.toHeight.get()),
new KeyValue(writableWidth, expansionManager.toWidth.get()))
);
现在您不会看到故障,并且在调整框大小时列表会很好地显示。事实上,我会增加第二个关键帧的持续时间。
编辑
我有另一种方法来避免“故障”。它还可以改进动画效果,因为当标题列表收缩时列表也将可见。
收缩带标题列表时,首先删除列表,因此 super.computePrefHeight(width)
和 super.computePrefWidth(height)
获得新的大小的小盒子。这有一个明显的缺点,即在下一次扩展时,必须再次添加列表,并且会发生故障。
为了避免这种情况,我们不会删除该列表。首先,我们在 ExpansionManager
上创建两个新字段:
Double minWidth = 0.0;
Double minHeight = 0.0;
然后我们得到盒子的最小尺寸(在第一次展开时),并在每次收缩时使用它:
@Override
protected double computePrefHeight(double width) {
...
if (expansionManager.layoutState == ExpansionManager.LayoutState.REQUEST_ANIMATION) {
if(expansionManager.minHeight==0d){
expansionManager.minHeight=getHeight();
}
expansionManager.fromHeight = getHeight();
expansionManager.stepHeight = expansionManager.fromHeight;
expansionManager.toHeight = expanded?super.computePrefHeight(width):
expansionManager.minHeight;
return expansionManager.fromHeight;
}
}
@Override
protected double computePrefWidth(double height) {
...
if (expansionManager.layoutState == ExpansionManager.LayoutState.REQUEST_ANIMATION) {
if(expansionManager.minWidth==0d){
expansionManager.minWidth=getWidth();
}
expansionManager.fromWidth = getWidth();
expansionManager.stepWidth = expansionManager.fromWidth;
expansionManager.toWidth = expanded?super.computePrefWidth(height):
expansionManager.minWidth;
return expansionManager.fromWidth;
}
}
最后,我们需要隐藏任何收缩后的列表,否则会看到一个小边框,将expand()
和contract()
方法改为调用requestLayout()
,假设框子列表不再被修改(第一次调用除外):
@Override
protected void layoutChildren() {
timeline.setOnFinished((done) -> {
expansionManager.layoutState = ExpansionManager.LayoutState.IDLE;
listView.setVisible(expanded);
timeline = null;
});
}
private void expand() {
expansionManager.layoutState = ExpansionManager.LayoutState.REQUEST_ANIMATION;
expanded = true;
listView.setVisible(true);
if(this.getChildren().size()==1){
this.getChildren().add(listView);
}
requestLayout();
}
private void contract() {
expansionManager.layoutState = ExpansionManager.LayoutState.REQUEST_ANIMATION;
expanded = false;
requestLayout();
}
关于JavaFX Glitches 动画非标准小部件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27770923/
Closed. This question needs to be more focused。它当前不接受答案。
我正在尝试使用 JavaFX 证明一个可扩展的小部件,它与 TitledPane 的不同之处在于标签周围的边框随着小部件的扩展而增长。我找到了一种方法。 但是我有一个奇怪的故障,在展开/折叠一两次后出
我在 IE9、:hover 和 CSS 背景属性中出现了一些非常奇怪的行为。 这几乎就像悬停和非悬停属性在不应该的时候交换了(换句话说,悬停属性变成了非悬停属性)。我只是用背景颜色和 SVG 渐变进行
我在使用 Firefox 的网站上遇到了一个“小”问题。在 Google Chrome 和 Safari 上,它工作得很好。 它应该是什么(Chrome 和 Safari): Firefox 上的问题
我一直在 glitch.com 中摆弄 HTML 代码,我想知道如何让某人输入一个输入并保存该输入,以便他或其他人可以看到它,有点像消息,有没有办法使用 JavaScript 的 console.lo
按住单个箭头键时,该功能可以正常工作。 但是,当我按住第二个箭头键并释放第二个键时,就会出现问题,不再检测到第一个按住的键。 我的函数的简化版本如下: document.body.onkeyup =
我在移动网站上使用 jQuery Mobile (v1.4.5.) 时遇到固定页脚的一些故障。 当有很多文本(需要滚动)时,没有问题。当文本很少(不需要滚动)时,没有问题。 当文本刚好需要稍微滚动一下
我使用 Glitch 编写一个 WebVR 项目。如果我直接在views/index.html中设置脚本,效果很好。但是如果我将脚本保存在 js/opencloserawer.js 中并将其导入到 i
我是 bootstrap 的新手,正在学习。我讨厌演示示例,它破坏了语义以使其看起来不错。无论如何... 我在示例网站上工作,theavcorp.com ,并在学习 Bootstrap 时尽量不要“破
我试图在将鼠标悬停在某个元素上时更改该元素的宽度。它似乎可以工作,但只要我将鼠标悬停在元素上,它就会一直过渡,从而导致类似故障的循环。我怎样才能使转换只发生一次? 谢谢。 html:
这个问题已经有答案了: Why doesn't adding CORS headers to an OPTIONS route allow browsers to access my API? (36
我试图在 C 中创建一个矩阵来求解拉普拉斯算子 然而,这是错误的。我已经在矩阵的初始化阶段找到了问题。程序每次运行时,都会在一个元素中放置一个看似随机的值。这个数字每次都会改变,表明代码不稳定,如果矩
我正在尝试为网站制作故障文本效果。在 Stackoverflow 上,它工作得很好。目前很好。 但问题不在我的元素文件夹中。如果您想查看它,请点击此处下载它: Download 这是 HTML、CSS
我网站的用户在执行任何 jQuery 代码之前在每个页面上看到了一个半秒故障。此代码操纵页面,因此您可以明显地看到元素在一大块中移动,使用户体验感到笨拙。我希望页面在 JavaScript 运行之前完
我在使用 Salat 时遇到了一个奇怪的问题,尤其是在我运行 Play 网络应用程序时会发生这种情况。 这是堆栈跟踪: Caused by: java.util.concurrent.Executio
我有一个子菜单,当悬停在导航元素上时,它会变为可见。当该元素不再悬停时,子菜单将变为不可见并向上移动。我已经在下面附上了我的部分代码。我面临的问题是,由于子菜单就在导航元素的正下方,向上移动会在转换期
如何在 Glitch.com 上创建和使用 Python 3.7? 我创建了一个项目。默认的 Python 版本是旧的。 我使用这些文件在 Glitch 上运行 Python: 主文件 import
我正在使用 BottomNavigationView 并将 ListView 添加到我的布局中。添加这个ListView后,之前的屏幕不会消失,并且这个新屏幕会覆盖之前的屏幕。有人知道为什么会发生这种
一般的 IE8 和 Javascript:导致 IE8 性能故障的常见问题是什么?有人知道在为 IE8 开发脚本时要避免的一系列问题和事情吗?生成在 Firefox 上运行时间为 200 毫秒,在 I
下面脚本的目的是允许用户发布新的更新并在不刷新页面的情况下删除它们:这就是我使用 AJAX 的原因。 有两个小故障: 当用户发布更新时,它会正确保存在数据库中,并且正确的更新会在我的表格中向下滑动,但
我是一名优秀的程序员,十分优秀!