草庐IT

java - 设置 Nimbus 按钮的按钮 "background"

coder 2024-04-02 原文

我正在开发一个使用 Nimbus 外观的应用程序。有一个表格,一列包含按钮(使用 Table Button Column from Rob Camick )。这确实有效,但结果不是我所期望的。我试图修复外观,但无济于事。

所以问题是:如何更改 Nimbus 按钮的“背景”(圆角矩形之外的区域)?最好以一种非 hacky 的方式:-)

使用默认的表格列按钮,结果如下所示:

如您所见,奇数(白色)行的背景(我指的是按钮圆角矩形之外的区域)是错误的。产生此输出的代码是:

public Component getTableCellRendererComponent(
        JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
    if (isSelected) {
        renderButton.setForeground(table.getSelectionForeground());
        renderButton.setBackground(table.getSelectionBackground());
    } else {
        renderButton.setForeground(table.getForeground());
        renderButton.setBackground(table.getBackground());
    }

    if (hasFocus) {
        renderButton.setBorder( focusBorder );
    } else {
        renderButton.setBorder( originalBorder );
    }

    // <snip some code>

    renderButton.setOpaque(true);

    return renderButton;
}

renderButton 是默认 JButton 的一个实例。我试过弄乱按钮的背景颜色,但结果并不像我最初预期的那样:

        Color alternate = (Color)LookAndFeel.getDesktopPropertyValue("Table.alternateRowColor", Color.lightGray);
        Color normal = (Color)LookAndFeel.getDesktopPropertyValue("Table.background", Color.white);
        if (row % 2 == 0) {
            renderButton.setBackground(normal);
        } else {
            renderButton.setBackground(alternate);
        }

这会产生:

所以这一次在第一张图片中看起来不错的按钮现在很糟糕,反之亦然。根据背景颜色属性,按钮的内部背景(圆角矩形内的区域)看起来确实具有正确的颜色(这是通过 setBackground() 调用真正修改的内容)。但是外面的区域完全不对。好吧,让我们把两者结合起来:

        Color alternate = table.getBackground();
        Color normal = (Color)LookAndFeel.getDesktopPropertyValue("Table.background", Color.white);
        if (row % 2 == 0) {
            renderButton.setBackground(normal);
        } else {
            renderButton.setBackground(alternate);
        }

结果:

所以现在“背景”看起来是正确的,但是按钮看起来不再像 Nimbus 按钮了。如何使“背景”具有正确的颜色,同时看起来仍然像 Nimbus 按钮?

最佳答案

下面是一种 hacky 方式,跟进@Piro 的建议:使用带有按钮的 JPanel 作为子组件。这本身就是一个好主意,因为我们真的不想触摸按钮的“内部”背景视觉效果。

当强制 Nimbus 内部不使用 JPanel 的默认背景 而是使用给定的面板实例 的背景时,这里出现了黑客攻击这需要依赖实现细节,特别是背景颜色的查找机制。这发生在 SynthStyle.getColor() 中:

// If the developer has specified a color, prefer it. Otherwise, get
// the color for the state.
Color color = null;
if (!id.isSubregion()) {
    if (type == ColorType.BACKGROUND) {
        color = c.getBackground();
    }
    ....
}

if (color == null || color instanceof UIResource) {
    // Then use what we've locally defined
    color = getColorForState(context, type);
}

翻译:它确实查询了实例的颜色,但如果实例颜色是 UIResource,它会用默认值否决它——如果用作渲染器,通常就是这种情况。所以诀窍(SynthBooleanRenderer 尝试不成功,但那是另一回事 ;-) 是使实例颜色不是 UIResource。另一个怪癖是 UIResource 是确保条纹颜色所必需的 - 这不是 UIResource 类型,哈哈 - 被应用......直观,不是吗......

public class RendererPanel implements TableCellRenderer {

    private JComponent panel;
    private JButton button;
    public RendererPanel() {
        panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(3, 10, 2, 10));
        button = new JButton();
        panel.add(button);
    }

    @Override
    public Component getTableCellRendererComponent(JTable table,
            Object value, boolean isSelected, boolean hasFocus, int row,
            int column) {
        // suggestion by Piro - use background of default
        DefaultTableCellRenderer dt = (DefaultTableCellRenderer) table.getDefaultRenderer(Object.class);
        dt.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        // first try: set the color as-is - doesn't work
        // panel.setBackground(dt.getBackground());
        // second try: set color as not ui-resource
        // that's working because at this point we already have the color that will be used
        // let's hinder synth background color searching to fall back to component defaults
        panel.setBackground(new Color(dt.getBackground().getRGB()));
        // hack: unwrap ui-resource as needed
        // updateBackground(isSelected ? table.getSelectionBackground() : table.getBackground(), row);
        button.setText(String.valueOf(value));
        return panel;
    }

    private void updateBackground(Color color, int row) {
        Color hack = row % 2 == 0 ? unwrap(color) : color;
        panel.setBackground(hack);
    }

    private Color unwrap(Color c) {
        if (c instanceof UIResource) {
            return new Color(c.getRGB());
        }
        return c;
    }

}

屏幕截图:解包 hack

屏幕截图:使用默认颜色(来自为 Object.class 安装的渲染器)

非 hacky 的出路可能是(没有在这里尝试,但记得曾经做过一次)用样式注册一个区域,类似于 NimbusDefaults 内部所做的:

register(Region.PANEL, "Table:\"Table.cellRenderer\"");

这里的问题是没有公共(public) api 可以这样做(或者可能是我对 Synth 了解不够 ;-)

关于java - 设置 Nimbus 按钮的按钮 "background",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18197505/

有关java - 设置 Nimbus 按钮的按钮 "background"的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  3. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  4. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  5. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  6. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  7. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  8. ruby-on-rails - date_field_tag,如何设置默认日期? [ rails 上的 ruby ] - 2

    我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问

  9. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  10. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

随机推荐