Java 7 JColorChooser: отключить слайдер прозрачности
JDK 7 добавил новый слайдер прозрачности в JColorChooser:
Проблема в том, что я не хочу, чтобы мои пользователи могли выбирать прозрачные цвета. К сожалению, нет простого способа отключить слайдер.
Один из способов избавиться от прозрачности - это просто создать новый цвет на основе выбранного, но удалить значение альфа. Однако это создает ложное впечатление на пользователя, поскольку ползунок теперь фактически ничего не делает, и я не хотел бы иметь бесполезный элемент пользовательского интерфейса.
Поэтому мой вопрос: как лучше избавиться от слайдера прозрачности?
PS: IMO, странно, что они просто добавили бы слайдер и установили его поведение по умолчанию. Это может вызвать много ошибок в программах JDK 6, которые не ожидают, что средство выбора цвета возвратит цвет с альфа-значением.
5 ответов
Согласно документации, можно просто изменить / настроить существующие классы. Поэтому рекомендуемый способ - создать свои собственные ChooserPanels (их необходимо расширить AbstractColorChooserPanel
), а затем вызвать
JColorChooser jc = new JColorChooser();
jc.setChooserPanels(new AbstractColorChooserPanel[]{yourChooserPanel});
В качестве альтернативы, если вы ищете более быстрый / противный / более уродливый способ сделать это, напишите это для вас:
private static void removeTransparencySlider(JColorChooser jc) throws Exception {
AbstractColorChooserPanel[] colorPanels = jc.getChooserPanels();
for (int i = 1; i < colorPanels.length; i++) {
AbstractColorChooserPanel cp = colorPanels[i];
Field f = cp.getClass().getDeclaredField("panel");
f.setAccessible(true);
Object colorPanel = f.get(cp);
Field f2 = colorPanel.getClass().getDeclaredField("spinners");
f2.setAccessible(true);
Object spinners = f2.get(colorPanel);
Object transpSlispinner = Array.get(spinners, 3);
if (i == colorPanels.length - 1) {
transpSlispinner = Array.get(spinners, 4);
}
Field f3 = transpSlispinner.getClass().getDeclaredField("slider");
f3.setAccessible(true);
JSlider slider = (JSlider) f3.get(transpSlispinner);
slider.setEnabled(false);
Field f4 = transpSlispinner.getClass().getDeclaredField("spinner");
f4.setAccessible(true);
JSpinner spinner = (JSpinner) f4.get(transpSlispinner);
spinner.setEnabled(false);
}
}
Удачи с этим:)
Хотя это зависит от реализации, вы можете удалить конкретные подклассы AbstractColorChooserPanel
по имени.
Этот пример удаляет все, кроме панели RGB:
AbstractColorChooserPanel[] ccPanels = chooser.getChooserPanels();
for (AbstractColorChooserPanel ccPanel : ccPanels) {
System.out.println(ccPanel.getDisplayName());
String name = ccPanel.getClass().getSimpleName();
if (!"DefaultRGBChooserPanel".equals(name))
tcc.removeChooserPanel(ccPanel);
}
Этот пример восстанавливает панель HSB:
for (AbstractColorChooserPanel ccPanel : ccPanels) {
String name = ccPanel.getClass().getSimpleName();
if ("DefaultHSBChooserPanel".equals(name))
tcc.addChooserPanel(ccPanel);
}
Вам нужно будет определить нужные имена эмпирически.
Другие ответы здесь показывают, как удалить ползунки прозрачности из экземпляра JColorChooser, но основным способом использования JColorChooser является статический showDialog
метод, в этом случае вы не получите доступ к экземпляру. Поэтому я представляю два метода, один из которых скрывает элементы управления от экземпляра JColorChooser, и метод замены для showDialog
который имеет showTransparencyControls
в качестве дополнительного параметра:
import java.awt.*;
import java.awt.event.ActionListener;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import javax.swing.*;
import javax.swing.colorchooser.AbstractColorChooserPanel;
class SwingUtil {
/**
* Hides controls for configuring color transparency on the specified
* color chooser.
*/
public static void hideTransparencyControls(JColorChooser cc) {
AbstractColorChooserPanel[] colorPanels = cc.getChooserPanels();
for (int i = 0; i < colorPanels.length; i++) {
AbstractColorChooserPanel cp = colorPanels[i];
try {
Field f = cp.getClass().getDeclaredField("panel");
f.setAccessible(true);
Object colorPanel = f.get(cp);
Field f2 = colorPanel.getClass().getDeclaredField("spinners");
f2.setAccessible(true);
Object sliders = f2.get(colorPanel);
Object transparencySlider = java.lang.reflect.Array.get(sliders, 3);
if (i == colorPanels.length - 1)
transparencySlider = java.lang.reflect.Array.get(sliders, 4);
Method setVisible = transparencySlider.getClass().getDeclaredMethod(
"setVisible", boolean.class);
setVisible.setAccessible(true);
setVisible.invoke(transparencySlider, false);
} catch (Throwable t) {}
}
}
/**
* Shows a modal color chooser dialog and blocks until the dialog is
* closed.
*
* @param component the parent component for the dialog; may be null
* @param title the dialog's title
* @param initialColor the initial color set when the dialog is shown
* @param showTransparencyControls whether to show controls for
* configuring the color's transparency
* @return the chosen color or null if the user canceled the dialog
*/
public static Color showColorChooserDialog(Component component,
String title, Color initialColor, boolean showTransparencyControls) {
JColorChooser pane = new JColorChooser(
initialColor != null ? initialColor : Color.white);
if (!showTransparencyControls) hideTransparencyControls(pane);
Color[] result = new Color[1];
ActionListener okListener = e -> result[0] = pane.getColor();
JDialog dialog = pane.createDialog(component, title, true, pane, okListener, null);
dialog.setVisible(true);
dialog.dispose();
return result[0];
}
}
Вот небольшая модификация ответа аймерика, которая полностью их скрывает, а не отключает.
private static void removeTransparencySlider(JColorChooser jc) throws Exception {
AbstractColorChooserPanel[] colorPanels = jc.getChooserPanels();
for (int i = 1; i < colorPanels.length; i++) {
AbstractColorChooserPanel cp = colorPanels[i];
Field f = cp.getClass().getDeclaredField("panel");
f.setAccessible(true);
Object colorPanel = f.get(cp);
Field f2 = colorPanel.getClass().getDeclaredField("spinners");
f2.setAccessible(true);
Object spinners = f2.get(colorPanel);
Object transpSlispinner = Array.get(spinners, 3);
if (i == colorPanels.length - 1) {
transpSlispinner = Array.get(spinners, 4);
}
Field f3 = transpSlispinner.getClass().getDeclaredField("slider");
f3.setAccessible(true);
JSlider slider = (JSlider) f3.get(transpSlispinner);
slider.setEnabled(false);
slider.setVisible(false);
Field f4 = transpSlispinner.getClass().getDeclaredField("spinner");
f4.setAccessible(true);
JSpinner spinner = (JSpinner) f4.get(transpSlispinner);
spinner.setEnabled(false);
spinner.setVisible(false);
Field f5 = transpSlispinner.getClass().getDeclaredField("label");
f5.setAccessible(true);
JLabel label = (JLabel) f5.get(transpSlispinner);
label.setVisible(false);
}
}
Java 9 добавляет новое свойство AbstractColorChooserPanel
управлять этими ползунками:
public void setColorTransparencySelectionEnabled(boolean b);
public boolean isColorTransparencySelectionEnabled();
Существует также новая перегрузка статического JColorChooser.showDialog
метод для указания того же свойства:
public static Color showDialog(Component component, String title, Color initialColor,
boolean colorTransparencySelectionEnabled);
Ожидается, что Java 9 будет выпущена в марте 2017 года.