Сравнение строки в нечувствительном к регистру образом кажется чем-то тривиальным, но это не так. Я буду использовать Python 3, так как Python 2 недостаточно развит здесь.
Первое, что следует отметить, что конверсии case-remove в unicode не являются тривиальными. Существует текст, для которого text.lower() != text.upper().lower()
, например "ß"
:
"ß".lower()
#>>> 'ß'
"ß".upper().lower()
#>>> 'ss'
Но скажем, вы хотели без лишних сравнений сравнить "BUSSE"
и "Buße"
. Heck, вы, вероятно, также хотите сравнить "BUSSE"
и "BUẞE"
equal - это новая форма капитала. Рекомендуемым способом является использование casefold
:
help(str.casefold)
#>>> Help on method_descriptor:
#>>>
#>>> casefold(...)
#>>> S.casefold() -> str
#>>>
#>>> Return a version of S suitable for caseless comparisons.
#>>>
Не используйте только lower
. Если casefold
недоступен, выполнение .upper().lower()
помогает (но только несколько).
Затем вы должны рассмотреть акценты. Если ваш рендерер шрифта хорош, вы, вероятно, думаете "ê" == "ê"
- но это не так:
"ê" == "ê"
#>>> False
Это потому, что они на самом деле
import unicodedata
[unicodedata.name(char) for char in "ê"]
#>>> ['LATIN SMALL LETTER E WITH CIRCUMFLEX']
[unicodedata.name(char) for char in "ê"]
#>>> ['LATIN SMALL LETTER E', 'COMBINING CIRCUMFLEX ACCENT']
Самый простой способ дело в том, что это unicodedata.normalize
. Вероятно, вы хотите использовать нормализацию NFKD, но не стесняйтесь проверить документацию. Затем выполняется
unicodedata.normalize("NFKD", "ê") == unicodedata.normalize("NFKD", "ê")
#>>> True
. Чтобы закончить, здесь это выражается в функциях:
import unicodedata
def normalize_caseless(text):
return unicodedata.normalize("NFKD", text.casefold())
def caseless_equal(left, right):
return normalize_caseless(left) == normalize_caseless(right)
Это относительно простая концепция (без обид).
Для начала не смешивайте свой код с JApplet
и JFrame
. Если вы хотите использовать свое приложение в этих двух средах, отделите логику на отдельный компонент (например, JPanel
), который вы можете легко добавить к нему. Вы действительно не должны добавлять контейнер верхнего уровня в другой контейнер верхнего уровня (добавление апплета в фрейм) - это грязно.
Избегайте переопределения методов paint
для контейнеров верхнего уровня (например, JApplet
) вместо этого используйте пользовательский компонент (например, JPanel
) и переопределите его метод paintComponent
.
В вашем примере вы должны называть super.paint
, а не super.paintComponents
. paint
делает важную работу, вы не хотите ее пропускать, но вы должны использовать JComponent#paintComponent
MouseListener
s, который должен быть добавлен к компонентам, которые вы заинтересованы в управлении событиями мыши. Поскольку clicked
никогда не добавляется в какие-либо контейнеры, он никогда не получит события мыши.
Взгляните на
[/g4]
public class SimplePaint03 {
public static void main(String[] args) {
new SimplePaint03();
}
public SimplePaint03() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new PaintPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class PaintPane extends JPanel {
private List<Shape> grid;
private List<Shape> fill;
public PaintPane() {
grid = new ArrayList<>(5);
fill = new ArrayList<>(5);
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
for (Shape shape : grid) {
if (shape.contains(e.getPoint())) {
if (fill.contains(shape)) {
fill.remove(shape);
} else {
fill.add(shape);
}
}
}
repaint();
}
});
int colWidth = 200 / 50;
int rowHeight = 200 / 50;
for (int row = 0; row < 50; row++) {
for (int col = 0; col < 50; col++) {
grid.add(new Rectangle(colWidth * col, rowHeight * row, colWidth, rowHeight));
}
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
for (Shape cell : fill) {
g2d.fill(cell);
}
g2d.setColor(Color.BLACK);
for (Shape cell : grid) {
g2d.draw(cell);
}
}
}
}
Дополнительно
Информация из одного цикла краски в другой не поддерживается. Вы должны перекрасить компонент точно так, как хотите. Это означает, что вам нужно будет сохранить список точек щелчка, которые можно перекрасить в любое время.
Начните с чтения учебника Swing на пользовательской живописи .
Пользовательская покраска выполняется путем переопределения метода paintComponent () JPanel или JComponent (). Затем вы добавляете панель в JApplet.
Если вы хотите только нарисовать определенные квадраты, тогда вам понадобится Список, чтобы отслеживать, какие ячейки нужно рисовать. Затем каждый раз, когда вы перерисовываете компонент, вам нужно пройти через список и нарисовать ячейки.
Ваш MouseListener не будет расширять JApplet. Когда вы нажимаете на ячейку, вы обновляете список сверху, чтобы указать, что ячейка должна быть нарисована. Затем вы будете вызывать repaint () на панели, чтобы вызвать ваш код рисования.
Вы также можете посмотреть пользовательские подходы к рисованию , который дает два разных способа сделать этот тип рисунка в зависимости от вашего точного требования.