Paepoi » PyObjC Tips » その他 NSControl
その他 NSControl
最終更新日 2024.08.25
個別ページを作るまでもないものを。
NSTextField のサブクラスなので NSTextField のメソッドも利用できます。
文字列の選択に特化しているようです。

又内部の NSMenu にアクセスできますので画像付きのポップアップも利用できます。
未選択状態は用意されていないので必要な場合は自分で作る必要があります。



個別ページを作るまでもないものを。
NSComboBox
右にある逆三角形をタップするとプルダウンして選択できます。NSTextField のサブクラスなので NSTextField のメソッドも利用できます。
文字列の選択に特化しているようです。
#!/usr/bin/env python3
import AppKit, objc
items = [
'やっぱり超望遠で野鳥でしょ',
'GoPro を固定してツーリング動画',
'電車だよ、わかんねえかなぁ',
'靴に付いたカメラで空を見上げたい'
]
class MyView(AppKit.NSView):
def initWithFrame_(self, rect):
objc.super(MyView, self).initWithFrame_(rect)
#
# NSComboBox @ NSTextField のサブクラス
# 高さを厳密にしないとズレて表示されるのでこんな感じに
#
self.cbox = AppKit.NSComboBox.labelWithString_('何が撮りたい?')
h = self.cbox.frameSize()[1]
self.cbox.setFrame_(((10, 10), (200, h)))
self.cbox.addItemsWithObjectValues_(items)
self.addSubview_(self.cbox)
#
return self
def isFlipped(self):
# 左上を原点にする
return True
class MyWindow(AppKit.NSWindow):
def init(self):
rect = AppKit.NSMakeRect(0, 0, 220, 100)
objc.super(MyWindow, self).initWithContentRect_styleMask_backing_defer_(
rect,
AppKit.NSTitledWindowMask |
AppKit.NSClosableWindowMask |
AppKit.NSResizableWindowMask |
AppKit.NSMiniaturizableWindowMask,
AppKit.NSBackingStoreBuffered, False)
# NSView
self.canvas = MyView.alloc().initWithFrame_(rect)
self.contentView().addSubview_(self.canvas)
# etc
self.setTitle_('Sample')
self.setDelegate_(self)
return self
def windowWillClose_(self, sender):
'''
終了時に値を書き出し
何も選択していない場合は -1 になる
'''
num = self.canvas.cbox.indexOfSelectedItem()
if num > -1:
print(self.canvas.cbox.objectValueOfSelectedItem())
class AppDelegate(AppKit.NSObject):
wins = []
def applicationDidFinishLaunching_(self, notification):
window = MyWindow.new()
window.makeKeyAndOrderFront_(window)
self.wins.append(window)
AppKit.NSApp.activateIgnoringOtherApps_(True)
def applicationSupportsSecureRestorableState_(self, app):
return True
class AppMenu(AppKit.NSMenu):
def init(self):
objc.super(AppMenu, self).init()
item_app = AppKit.NSMenuItem.new()
self.addItem_(item_app)
menu_app = AppKit.NSMenu.new()
item_app.setSubmenu_(menu_app)
# quit menu
item_quit = AppKit.NSMenuItem.new()
item_quit.initWithTitle_action_keyEquivalent_('Quit App', 'terminate:', 'q')
menu_app.addItem_(item_quit)
return self
AppKit.NSApplication.sharedApplication()
AppKit.NSApp.setMainMenu_(AppMenu.new())
AppKit.NSApp.setDelegate_(AppDelegate.new())
NSApp.run()

NSPopUpButton
NSCombobox と同様ですがこちらはどの部分をタップしてもプルダウンできます。又内部の NSMenu にアクセスできますので画像付きのポップアップも利用できます。
未選択状態は用意されていないので必要な場合は自分で作る必要があります。
#!/usr/bin/env python3
import AppKit, objc
items = ['Apache の', 'アイコンを', '勝手に使って', 'ごめんなチャイ']
class MyView(AppKit.NSView):
def initWithFrame_(self, rect):
objc.super(MyView, self).initWithFrame_(rect)
#
# NSPopUpButton @ NSButton のサブクラス
# autoenablesItems プロパティを True にしないと変化しない
#
self.pbtn = AppKit.NSPopUpButton.alloc().initWithFrame_pullsDown_(((10, 10), (200, 40)), False)
self.pbtn.addItemsWithTitles_(items)
self.pbtn.setAutoenablesItems_(True)
self.addSubview_(self.pbtn)
# ICON のセット
for i, s in enumerate(['a.png', 'c.png', 'f.png', 'p.png']):
# apache のアイコンを拝借、皆デフォルトで入っているよね?
path = f'/usr/share/httpd/icons/{s}'
image = AppKit.NSImage.alloc().initWithContentsOfFile_(path)
menu = self.pbtn.itemArray()[i]
menu.setImage_(image)
# 選択した時にアクションさせる
menu.setTarget_(self)
menu.setAction_('onSelect:')
#
return self
def onSelect_(self, sender):
# 選択を変更するとココに来る
print(sender.title())
def isFlipped(self):
# 左上を原点にする
return True
class MyWindow(AppKit.NSWindow):
def init(self):
rect = AppKit.NSMakeRect(0, 0, 220, 100)
objc.super(MyWindow, self).initWithContentRect_styleMask_backing_defer_(
rect,
AppKit.NSTitledWindowMask |
AppKit.NSClosableWindowMask |
AppKit.NSResizableWindowMask |
AppKit.NSMiniaturizableWindowMask,
AppKit.NSBackingStoreBuffered, False)
# NSView
self.canvas = MyView.alloc().initWithFrame_(rect)
self.contentView().addSubview_(self.canvas)
# etc
self.setTitle_('Sample')
return self
class AppDelegate(AppKit.NSObject):
wins = []
def applicationDidFinishLaunching_(self, notification):
window = MyWindow.new()
window.makeKeyAndOrderFront_(window)
self.wins.append(window)
AppKit.NSApp.activateIgnoringOtherApps_(True)
def applicationSupportsSecureRestorableState_(self, app):
return True
class AppMenu(AppKit.NSMenu):
def init(self):
objc.super(AppMenu, self).init()
item_app = AppKit.NSMenuItem.new()
self.addItem_(item_app)
menu_app = AppKit.NSMenu.new()
item_app.setSubmenu_(menu_app)
# quit menu
item_quit = AppKit.NSMenuItem.new()
item_quit.initWithTitle_action_keyEquivalent_('Quit App', 'terminate:', 'q')
menu_app.addItem_(item_quit)
return self
AppKit.NSApplication.sharedApplication()
AppKit.NSApp.setMainMenu_(AppMenu.new())
AppKit.NSApp.setDelegate_(AppDelegate.new())
AppKit.NSApp.run()

NSSlider
NSSlider は名前のとおりスライダーです。#!/usr/bin/env python3
import AppKit, objc
class MyView(AppKit.NSView):
def initWithFrame_(self, rect):
objc.super(MyView, self).initWithFrame_(rect)
#
# 普通に作る、初期値は 0.0〜1.0
#
slider1 = AppKit.NSSlider.sliderWithTarget_action_(self, 'onSlide1:')
slider1.setFrameOrigin_((10, 10))
self.addSubview_(slider1)
#slider1.setSliderType_(NSSliderTypeCircular) # 使いづらい
#
# カスタマイズ版、メソッド名で何を指定しているか解るはず
# ちなみに整数で指定しても勝手に float と解釈してくれる
#
slider2 = AppKit.NSSlider.sliderWithValue_minValue_maxValue_target_action_(
120, 80, 200, self, 'onSlide2:')
# メモリの表示、線の数を指定
slider2.setNumberOfTickMarks_(7)
# メモリ上にしか止まらないように
slider2.setAllowsTickMarkValuesOnly_(True)
# 配置
slider2.setFrameOrigin_((10, 40))
self.addSubview_(slider2)
#
# 上記の数値を表示するラベル
#
self.label = AppKit.NSTextField.labelWithString_('80.0')
self.label.setFrameOrigin_((150, 40))
self.addSubview_(self.label)
#
return self
def onSlide1_(self, sender):
# 選択を変更するとココに来る
print(sender.floatValue())
def onSlide2_(self, sender):
# 選択を変更、label を変更
self.label.setStringValue_(f'{sender.floatValue()}')
# はみ出さないように
self.label.sizeToFit()
def isFlipped(self):
# 左上を原点にする
return True
class MyWindow(AppKit.NSWindow):
def init(self):
rect = AppKit.NSMakeRect(0, 0, 220, 100)
objc.super(MyWindow, self).initWithContentRect_styleMask_backing_defer_(
rect,
AppKit.NSTitledWindowMask |
AppKit.NSClosableWindowMask |
AppKit.NSResizableWindowMask |
AppKit.NSMiniaturizableWindowMask,
AppKit.NSBackingStoreBuffered, False)
# NSView
self.canvas = MyView.alloc().initWithFrame_(rect)
self.contentView().addSubview_(self.canvas)
# etc
self.setTitle_('Sample')
return self
class AppDelegate(AppKit.NSObject):
wins = []
def applicationDidFinishLaunching_(self, notification):
window = MyWindow.new()
window.makeKeyAndOrderFront_(window)
self.wins.append(window)
AppKit.NSApp.activateIgnoringOtherApps_(True)
def applicationSupportsSecureRestorableState_(self, app):
return True
class AppMenu(AppKit.NSMenu):
def init(self):
objc.super(AppMenu, self).init()
item_app = AppKit.NSMenuItem.new()
self.addItem_(item_app)
menu_app = AppKit.NSMenu.new()
item_app.setSubmenu_(menu_app)
# quit menu
item_quit = AppKit.NSMenuItem.new()
item_quit.initWithTitle_action_keyEquivalent_('Quit App', 'terminate:', 'q')
menu_app.addItem_(item_quit)
return self
AppKit.NSApplication.sharedApplication()
AppKit.NSApp.setMainMenu_(AppMenu.new())
AppKit.NSApp.setDelegate_(AppDelegate.new())
AppKit.NSApp.run()

NSSegmentedControl
NSSegmentedControl はボタンのグループ化を超簡単に実現してくれます。#!/usr/bin/env python3
import AppKit, objc
buttons = ['ボタンの', 'グループ化は', '簡単', 'です']
class MyView(AppKit.NSView):
def initWithFrame_(self, rect):
objc.super(MyView, self).initWithFrame_(rect)
#
# システム環境設定のディスプレイとかで使われているアレ
#
sc = AppKit.NSSegmentedControl.segmentedControlWithLabels_trackingMode_target_action_(
buttons, AppKit.NSSegmentSwitchTrackingSelectOne, self, 'onSeg:')
# インデックスで選択を指定
sc.setSelectedSegment_(1)
sc.setFrameOrigin_((10, 10))
self.addSubview_(sc)
#
return self
def onSeg_(self, sender):
# 選択を変更するとココに来る
print(sender.selectedSegment())
def isFlipped(self):
# 左上を原点にする
return True
class MyWindow(AppKit.NSWindow):
def init(self):
rect = AppKit.NSMakeRect(0, 0, 300, 100)
objc.super(MyWindow, self).initWithContentRect_styleMask_backing_defer_(
rect,
AppKit.NSTitledWindowMask |
AppKit.NSClosableWindowMask |
AppKit.NSResizableWindowMask |
AppKit.NSMiniaturizableWindowMask,
AppKit.NSBackingStoreBuffered, False)
# NSView
self.canvas = MyView.alloc().initWithFrame_(rect)
self.contentView().addSubview_(self.canvas)
# etc
self.setTitle_('Sample')
return self
class AppDelegate(AppKit.NSObject):
wins = []
def applicationDidFinishLaunching_(self, notification):
window = MyWindow.new()
window.makeKeyAndOrderFront_(window)
self.wins.append(window)
AppKit.NSApp.activateIgnoringOtherApps_(True)
def applicationSupportsSecureRestorableState_(self, app):
return True
class AppMenu(AppKit.NSMenu):
def init(self):
objc.super(AppMenu, self).init()
item_app = AppKit.NSMenuItem.new()
self.addItem_(item_app)
menu_app = AppKit.NSMenu.new()
item_app.setSubmenu_(menu_app)
# quit menu
item_quit = AppKit.NSMenuItem.new()
item_quit.initWithTitle_action_keyEquivalent_('Quit App', 'terminate:', 'q')
menu_app.addItem_(item_quit)
return self
AppKit.NSApplication.sharedApplication()
AppKit.NSApp.setMainMenu_(AppMenu.new())
AppKit.NSApp.setDelegate_(AppDelegate.new())
AppKit.NSApp.run()

Copyright(C) sasakima-nao All rights reserved 2002 --- 2025.