#java #blackberry #java-me #menu #menuitem
#java #ежевика #java-me #меню #элемент меню
Вопрос:
Я подготовил простой тестовый пример, демонстрирующий мою проблему.
Это всего лишь 1 файл (CheckMenu.java, перечисленного ниже) и мгновенно запускаемого.
Как только пользователь изменит метод сортировки, выбрав 1 из 2 элементов меню, как мне перерисовать лежащее в его основе ключевое поле фильтра? Я пытался вызвать myList.updateList() и myList.invalidate() — это не помогает — элементы myList не реорганизованы.
Также мне интересно, что использовать вместо устаревшего MenuItem.setText(строка)?
package mypackage;
import net.rim.device.api.system.*;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.util.Comparator;
import net.rim.device.api.util.StringUtilities;
import net.rim.device.api.collection.util.*;
public class CheckMenu extends UiApplication {
public static void main(String[] args) {
CheckMenu myApp = new CheckMenu();
myApp.enterEventDispatcher();
}
public CheckMenu() {
pushScreen(new MyScreen());
}
}
class MyScreen extends MainScreen {
KeywordFilterField myList = new KeywordFilterField();
MyItemList myItems = new MyItemList();
public MyScreen() {
setTitle(myList.getKeywordField());
myItems.doAdd(new MyItem(1, "Eins"));
myItems.doAdd(new MyItem(2, "Zwei"));
myItems.doAdd(new MyItem(3, "Drei"));
myItems.doAdd(new MyItem(4, "Vier"));
myList.setSourceList(myItems, new MyItem.MyProvider());
// XXX commenting the line below does not help
myList.setCallback(new MyListFieldCallback());
add(myList);
}
private MenuItem numMenu = new MenuItem("num sort", 0, 0) {
public void run() {
MyItem.NUMERIC_SORT = true;
Status.show("Use " toString());
setText("num sort u221A");
alphaMenu.setText("alpha sort");
myList.updateList();
}
};
private MenuItem alphaMenu = new MenuItem("alpha sort", 1, 0) {
public void run() {
MyItem.NUMERIC_SORT = false;
Status.show("Use " toString());
setText("alpha sort u221A");
numMenu.setText("num sort");
myList.updateList();
}
};
protected void makeMenu(Menu menu, int instance) {
super.makeMenu(menu, instance);
menu.add(numMenu);
menu.add(alphaMenu);
}
private class MyListFieldCallback implements ListFieldCallback {
public void drawListRow(ListField list, Graphics g, int index, int y, int width) {
Object obj = ((KeywordFilterField)list).getElementAt(index);
if(obj != null amp;amp; obj instanceof MyItem) {
MyItem item = (MyItem) obj;
g.drawText(item.toString(), 20 * (1 index), y);
} else if(index == 0) {
g.drawText(list.getEmptyString(), 0, y);
}
}
public Object get(ListField list, int index) {
return null;
}
public int getPreferredWidth(ListField list) {
return 0;
}
public int indexOfList(ListField list, String prefix, int start) {
return 0;
}
}
}
class MyItemList extends SortedReadableList {
public MyItemList() {
super(new MyItem.MyComparator());
}
protected void doAdd(Object obj) {
super.doAdd(obj);
}
protected boolean doRemove(Object obj) {
return super.doRemove(obj);
}
}
class MyItem {
public static boolean NUMERIC_SORT;
private int _num;
private String _name;
public MyItem(int num, String name) {
_num = num;
_name = name;
}
public String toString() {
return _num ": " _name;
}
static class MyComparator implements Comparator {
public int compare(Object obj1, Object obj2) {
if (! (obj1 instanceof MyItem amp;amp; obj2 instanceof MyItem))
throw new IllegalArgumentException("Cannot compare non-MyItems");
MyItem item1 = (MyItem) obj1;
MyItem item2 = (MyItem) obj2;
if (MyItem.NUMERIC_SORT) {
if (item1._num == item2._num)
return 0;
return (item1._num > item2._num ? 1 : -1);
}
return item1._name.compareTo(item2._name);
}
}
static class MyProvider implements KeywordProvider {
public String[] getKeywords(Object obj) {
if (obj instanceof MyItem) {
MyItem item = (MyItem) obj;
return new String[]{ Integer.toString(item._num), item._name };
}
return null;
}
}
}
ОБНОВЛЕНИЕ: я обновил код для использования makeMenu(), как было предложено Arhimed.
Я также разместил свой вопрос на форуме BlackBerry.
Спасибо! Алекс
Комментарии:
1. 1 за идеально структурированный / подготовленный вопрос.
Ответ №1:
Возможно, я не понимаю вашей проблемы….. Но, как я вижу, этот код отлично работает на симуляторе
import net.rim.device.api.system.*;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.util.Comparator;
import net.rim.device.api.util.StringUtilities;
import net.rim.device.api.collection.util.*;
public class CheckMenu extends UiApplication {
public static void main(String[] args) {
CheckMenu myApp = new CheckMenu();
myApp.enterEventDispatcher();
}
public CheckMenu() {
pushScreen(new MyScreen());
}
}
class MyScreen extends MainScreen {
KeywordFilterField myList = new KeywordFilterField();
MyItemList myItems = new MyItemList();
public MyScreen() {
setTitle(myList.getKeywordField());
myItems.doAdd(new MyItem(1, "Eins"));
myItems.doAdd(new MyItem(2, "Zwei"));
myItems.doAdd(new MyItem(3, "Drei"));
myItems.doAdd(new MyItem(4, "Vier"));
myList.setSourceList(myItems, new MyItem.MyProvider());
// XXX commenting the line below does not help
myList.setCallback(new MyListFieldCallback());
add(myList);
}
private MenuItem numMenu = new MenuItem("num sort", 0, 0) {
public void run() {
MyItem.NUMERIC_SORT = true;
Status.show("Use " toString());
setText("num sort u221A");
alphaMenu.setText("alpha sort");
myItems.sort();
myList.updateList();
}
};
private MenuItem alphaMenu = new MenuItem("alpha sort", 1, 0) {
public void run() {
MyItem.NUMERIC_SORT = false;
Status.show("Use " toString());
setText("alpha sort u221A");
numMenu.setText("num sort");
myItems.sort();
myList.updateList();
}
};
protected void makeMenu(Menu menu, int instance) {
super.makeMenu(menu, instance);
menu.add(numMenu);
menu.add(alphaMenu);
}
private class MyListFieldCallback implements ListFieldCallback {
public void drawListRow(ListField listField, Graphics g, int index, int y, int width) {
Object obj = ((KeywordFilterField)listField).getElementAt(index);
if(obj != null amp;amp; obj instanceof MyItem) {
MyItem item = (MyItem) obj;
g.drawText(item.toString(), 20 * (1 index), y);
} else if(index == 0) {
g.drawText("ssssssss", 0, y);
}
}
public Object get(ListField listField, int index) {
return null;
}
public int getPreferredWidth(ListField listField) {
return 0;
}
public int indexOfList(ListField listField, String prefix, int start) {
return 0;
}
}
}
class MyItemList extends SortedReadableList {
public MyItemList() {
super(new MyItem.MyComparator());
}
protected void doAdd(Object obj) {
super.doAdd(obj);
}
protected boolean doRemove(Object obj) {
return super.doRemove(obj);
}
}
class MyItem {
public static boolean NUMERIC_SORT;
private int _num;
private String _name;
public MyItem(int num, String name) {
_num = num;
_name = name;
}
public String toString() {
return _num ": " _name;
}
static class MyComparator implements Comparator {
public int compare(Object obj1, Object obj2) {
if (! (obj1 instanceof MyItem amp;amp; obj2 instanceof MyItem))
throw new IllegalArgumentException("Cannot compare non-MyItems");
MyItem item1 = (MyItem) obj1;
MyItem item2 = (MyItem) obj2;
if (MyItem.NUMERIC_SORT) {
if (item1._num == item2._num)
return 0;
return (item1._num > item2._num ? 1 : -1);
}
return item1._name.compareTo(item2._name);
}
}
static class MyProvider implements KeywordProvider {
public String[] getKeywords(Object obj) {
if (obj instanceof MyItem) {
MyItem item = (MyItem) obj;
return new String[]{ Integer.toString(item._num), item._name };
}
return null;
}
}
}
Комментарии:
1. При изменении числовой сортировки <-> алфавитной в меню — поле списка должно отображать 4 строки в разном порядке
2. ДА. Когда я меняю сортировку числовую <-> алфавитную в меню — в ListField отображаются 4 строки в другом порядке. Я просто добавляю myItems.sort(); в ваш код.
3. Верно, это решение моей проблемы (извините, сначала пропустил ваше добавление)! Мне это кажется более естественным, чем переназначение компаратора, как предлагает Arhimed.
4. повторное назначение Comparator было быстрым решением, чтобы вызвать повторную сортировку без необходимости копаться в документах API. 🙂 Я думал, вам достаточно просто получить представление о том, что не так с вашим рабочим процессом / логикой.
Ответ №2:
1). Как я могу изменить текст элемента меню? Я хотел бы отобразить / скрыть символ флажка u221A — в зависимости от того, какой порядок сортировки в данный момент выбран пользователем. Метод setText (String text) устарел, и я не уверен, как использовать setText (StringProvider text)?
Вместо использования addMenuItem(myMenu1);
переопределения makeMenu(Menu menu, int instance)
:
protected void makeMenu(Menu menu, int instance) {
super.makeMenu(menu, instance);
// add menu items on-the-fly
// generating their labels in accordance to some conditions
menu.add(new MenuItem("any label", 1, 1) {
public void run() {
// do smth useful
}
});
}
2). Как только пользователь изменит метод сортировки, выбрав 1 из 2
Элементы меню, как мне перерисовать
лежащее в основе KeywordFilterField? Я
попытался вызвать myList.updateList() и
myList.invalidate() — это не помогает.
Попробуйте закомментировать myList.setCallback(new MyListFieldCallback());
строку. Я полагаю, что KeywordFilterField
этот обратный вызов уже реализован каким-то определенным образом, поэтому, устанавливая свой пользовательский, ListFieldCallback
вы нарушаете поведение по умолчанию / ожидаемое поведение.
ОБНОВЛЕНИЕ об элементах меню:
Полностью избавьтесь от полей private MenuItem alphaMenu
и private MenuItem numMenu
. Генерируйте эти пункты меню «на лету»:
protected void makeMenu(Menu menu, int instance) {
super.makeMenu(menu, instance);
String label = "num sort" (MyItem.NUMERIC_SORT ? " u221A" : "");
menu.add(new MenuItem(label, 0, 0) {
public void run() {
MyItem.NUMERIC_SORT = true;
Status.show("Use " toString());
// setText("num sort u221A");
// alphaMenu.setText("alpha sort");
myList.updateList();
}
});
label = "alpha sort" (MyItem.NUMERIC_SORT ? "" : " u221A");
menu.add(new MenuItem(label, 1, 0) {
public void run() {
MyItem.NUMERIC_SORT = false;
Status.show("Use " toString());
// setText("alpha sort u221A");
// numMenu.setText("num sort");
myList.updateList();
}
});
}
ОБНОВИТЕ основную проблему:
class MyScreen extends MainScreen {
KeywordFilterField myList = new KeywordFilterField();
MyItemList myItems = new MyItemList();
public MyScreen() {
setTitle(myList.getKeywordField());
myItems.doAdd(new MyItem(1, "Eins"));
myItems.doAdd(new MyItem(2, "Zwei"));
myItems.doAdd(new MyItem(3, "Drei"));
myItems.doAdd(new MyItem(4, "Vier"));
myList.setSourceList(myItems, new MyItem.MyProvider());
// XXX commenting the line below does not help
myList.setCallback(new MyListFieldCallback());
add(myList);
}
protected void makeMenu(Menu menu, int instance) {
super.makeMenu(menu, instance);
String label = "num sort" (MyItem.NUMERIC_SORT ? " u221A" : "");
menu.add(new MenuItem(label, 0, 0) {
public void run() {
MyItem.NUMERIC_SORT = true;
Status.show("Use " toString());
// setText("num sort u221A");
// alphaMenu.setText("alpha sort");
myItems.setComparator(new MyItem.MyComparator());
myList.updateList();
}
});
label = "alpha sort" (MyItem.NUMERIC_SORT ? "" : " u221A");
menu.add(new MenuItem(label, 1, 0) {
public void run() {
MyItem.NUMERIC_SORT = false;
Status.show("Use " toString());
// setText("alpha sort u221A");
// numMenu.setText("num sort");
myItems.setComparator(new MyItem.MyComparator());
myList.updateList();
}
});
}
// .. the rest of the code is the same
Комментарии:
1. 1) Спасибо, но как переход с addMenuItem на makeMenu поможет мне изменять тексты меню во время выполнения?
2. Сделайте ваши тексты меню переменными и измените их с помощью условных выражений, makeMenu() — это динамический метод, он выполняется только при запросе меню
3. да, я имею в виду вообще не использовать
addMenuItem
. ПереопределениеmakeMenu
вместо этого оно будет вызываться каждый раз, когда пользователь нажимает кнопку меню на устройстве.4. Здравствуйте! Я обновил свой код, чтобы использовать makeMenu, но все еще задаюсь вопросом, что использовать вместо setText (строка). А также основная проблема, связанная с тем, что порядок элементов списка не изменяется, не устраняется путем комментирования myList.setCallback(new MyListFieldCallback()) .
5. @Alexander Farber: Я добавил раздел ОБНОВЛЕНИЯ о том, как использовать
makeMenu
. Однако у меня все еще нет идей по основной проблеме с полем списка. Мне нужно подумать об этом..