包含 HTML 文本的 JLabel 使用可用空间自动换行。如果将 JLabel 添加到 JSrollPane 中,他必须将 preferredSize 设置为合适的值,否则它不会换行。所有这些都应该与使用 LayoutManager 的 JPanel 中的其他组件一起正常工作。
因为我想要一个可调整大小的应用程序窗口,所以我扩展了 JScrollPane 以跟踪调整大小事件并动态更改与视口(viewport)宽度同步的大小。基本上它可以工作,但有时布局管理器对首选高度的计算是错误的(值太大或太小)。例如,穿过第一条线的红色边框的可见性表明高度的计算是错误的。
我无法用单个包装 JLabel 重现失败。
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class WrappedLabel implements Runnable {
public static void main( String[] args ){
SwingUtilities.invokeLater( new WrappedLabel() );
}
@Override
public void run(){
final JPanel panel = new JPanel( new GridBagLayout() );
final GridBagConstraints gc = new GridBagConstraints();
gc.fill = GridBagConstraints.BOTH;
gc.weightx = 1.0;
gc.weighty = 1.0;
{
gc.gridx = 0;
gc.gridy = 0;
final JLabel label = new JLabel(
"<html>" + "please add some more text here"
);
label.setBorder( BorderFactory.createLineBorder( Color.RED ) );
panel.add( label, gc );
}
{
gc.gridx = 0;
gc.gridy = 1;
final JLabel label = new JLabel(
"<html>" + "please add some more text here"
);
label.setBorder( BorderFactory.createLineBorder( Color.RED ) );
panel.add( label, gc );
}
final JFrame frame = new JFrame();
frame.add( new ScrollPane( panel ) );
frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
frame.setSize( 256, 256 );
frame.setVisible( true );
}
private class ScrollPane extends JScrollPane implements ComponentListener {
ScrollPane( Container view ){
super( view );
this.viewport.addComponentListener( this );
}
@Override
public void componentHidden( ComponentEvent ce ){
}
@Override
public void componentMoved( ComponentEvent ce ){
}
/** calculating required height is a 3 step process
* 1. sync width of client and viewport, set height of client to high value
* 2. let GridbagManager calculate required minimum size
* 3. set preferredSize and revalidate
**/
@Override
public void componentResized( ComponentEvent ce ){
assert( this.viewport == ce.getSource() );
final Container view = (Container) this.viewport.getView();
final int width = this.viewport.getExtentSize().width;
view.setPreferredSize( new Dimension( width, Integer.MAX_VALUE ) );
final int height = view.getLayout().preferredLayoutSize( view ).height;
view.setPreferredSize( new Dimension( width, height ) );
view.revalidate();
}
@Override
public void componentShown( ComponentEvent ce ){
}
}
}
最佳答案
显然,这可能是 GridBagLayout 中的一个错误,或者您正在以开发人员完全出乎意料的方式使用布局引擎。几个带有 HTML 的多行标签,设置首选大小并立即通过后门询问首选大小?啊!
我注意到有时在减小窗口大小时布局会不正确:滚动 Pane 内的面板不会减小并且出现水平滚动条。 (顺便说一句,我正在使用 Windows)。
此外,有时,如果垂直滚动条可见且面板高度很大,然后我增加窗口大小,面板高度仍然过大并且标签周围出现间隙:
对我来说,当我缩小窗口时,布局每隔一段时间就会出错;增加效果更好,但如果出错,每隔一段时间也是不正确的。我尝试调试和打印值到控制台; view.getLayout().preferredLayoutSize( view ) 似乎不仅取决于 view.setPreferredSize,还取决于面板和滚动 Pane 的当前大小。 GridBagLayout 的代码过于复杂,无法深入研究。
肮脏的黑客
既然每隔一次调整大小都会产生正确的结果,为什么不调整两次呢?在 ScrollPane.componentResized 处理程序中复制内容不成功,可能是因为 ScrollPane 的大小保持不变。 ScrollPane 本身需要使用不同的值调整两次大小。为了以最简单的方式对其进行测试,我对 JFrame 进行了子类化:它监听 componentResized 并将其子窗口的大小调整两次。必须通过 SwingUtilities.invokeLater 推迟第二次调整大小。
替换行
final JFrame frame = new JFrame();
frame.add( scroll );
通过
final MyFrame frame = new MyFrame(scroll);
并添加以下类:
private class MyFrame extends JFrame implements ComponentListener {
private Component child;
public MyFrame(Component child){
this.child=child;
setLayout(null);
getContentPane().add(child);
addComponentListener(this);
}
public void componentResized(ComponentEvent e) {
Dimension size=getContentPane().getSize();
child.setSize(new Dimension(size.width-1,size.height));
validate();
SwingUtilities.invokeLater(new ResizeRunner(size));
}
public void componentMoved(ComponentEvent e) {}
public void componentShown(ComponentEvent e) {}
public void componentHidden(ComponentEvent e) {}
private class ResizeRunner implements Runnable {
private Dimension size;
public ResizeRunner(Dimension size){
this.size=size;
}
public void run() {
child.setSize(size);
validate();
}
}
}
同样可以通过子类化布局管理器来实现。
显然,这种方法不够优雅且效率低下,但作为 JRE 错误的解决方法,如果没有其他帮助... ;-)
关于java - 带有包装 HTML 文本的 JLabel 作为 JScrollPane 客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13343909/
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这
所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.
只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我