NSTableView: как вы можете выделить элемент при щелчке правой кнопкой мыши?

#objective-c #nstableview

#objective-c #nstableview

Вопрос:

У меня есть NSTableView , к которому элементы добавляются без вмешательства пользователя. Когда пользователь возвращается в диалоговое окно, содержащее NSTableView элемент, и нажимает на элемент, этот элемент выделяется. Однако элемент не выделяется, если щелкнуть элемент правой кнопкой мыши. Есть ли способ выделить элемент, который щелкнут правой кнопкой мыши?

В настоящее время у меня есть следующее:

 void Dialog::menuAction(ui::Menu::Item* item)
{ 
  // Highlight the item clicked
  [tableView row:item select:YES]
  ...
}
  

Но, похоже, это не работает.

Комментарии:

1. это код Objective-C?

Ответ №1:

Мое решение, которое кажется самым чистым, показанным здесь до сих пор, состоит в том, чтобы подклассировать NSTableView и реализовать его menuForEvent сообщение. Просто сделайте свой табличный вид подклассом этого, и вы автоматически получите правильное поведение:

 @interface CustomTableView : NSTableView
@end

@implementation CustomTableView

- (NSMenu*) menuForEvent:(NSEvent*)event // override
{
    // Get to row at point
    NSInteger row = [self rowAtPoint:[self convertPoint:event.locationInWindow fromView:nil]];
    if (row >= 0) {
        // and check whether it is selected
        if (NOT [self isRowSelected:row]) {
            // No -> select that row
            [self selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
        }
    }
    return [super menuForEvent:event];
}

@end
  

Должно работать аналогично NSOutlineView .

Обратите внимание, как код решает, когда выделять строку. Это точно имитирует поведение, которое вы можете увидеть, например, в Finder:

  • Если щелкнуть правой кнопкой мыши по существующему выделению, особенно если это несколько элементов, они остаются выбранными.
  • Если щелкнуть правой кнопкой мыши за пределами текущего выделения, только что выбранная строка станет новым выделением.

Однако это не идеально: Finder изменяет выделение только после того, как пользователь фактически использует один из элементов контекстного меню. Если пользователь отменит всплывающее меню, выбор не изменится. Однако мой код изменяет выбор до того, как пользователь сможет выбрать из всплывающего меню. Не стесняйтесь улучшать это и делиться этим здесь.

Ответ №2:

Возможно, это не совсем то, что вы хотите, но это может помочь. У меня возникла проблема с получением строки, по которой щелкнули правой кнопкой мыши, чтобы получить контекстное меню. Я использую общий вид, а не табличный, и он находится в главном окне, а не в диалоговом окне.

У меня есть выход к моему внешнему виду. В объекте, который обрабатывает меню, у меня есть следующий метод:

 - (void) setSelectionFromClick {
    NSInteger theClickedRow = [myOutlineView clickedRow];
    NSIndexSet *thisIndexSet = [NSIndexSet indexSetWithIndex:theClickedRow];
    [myOutlineView selectRowIndexes:thisIndexSet byExtendingSelection:NO];
}
  

Я вызываю этот метод в начале каждого действия меню.

Выбранная строка устанавливается независимо от того, какая кнопка нажата. Но выделение изменяется автоматически только при нажатии левой кнопки мыши. Кстати, это также работает с щелчком мыши.

Комментарии:

1. Здесь вы получаете clickedRow, но в случае NSTableView мы не получаем то же значение, для которого пользователь щелкнул правой кнопкой мыши.

Ответ №3:

просто быстрая версия решения @Thomas Tempelmann.

 public class TableViewWithRightClickSelect: NSTableView
{
    override open func menu(for event: NSEvent) -> NSMenu?
    {
        let row = self.row(at: self.convert(event.locationInWindow, from: nil))
        if row >= 0
        {
            self.selectRowIndexes(IndexSet(integer: row), byExtendingSelection: false)
        }
        
        return super.menu(for: event)
    }
}