Paepoi » PyObjC Tips » NSButton
NSButton
最終更新日 2024.08.25
どんなスタイルがあるのかは作って確認したほうが早いので以下に。

どんなタイプがあるか、やはり作って確認したほうが早いので以下に。

NSMatrix と組み合わせて使います、以下サンプル。

ボタンスタイル
スタイル指定でどんな形のボタンになるかを決定します。どんなスタイルがあるのかは作って確認したほうが早いので以下に。
#!/usr/bin/env python3
# 左上基準のほうが配置が楽なので継承した NSView の上に置いています
# title プロパティには 'Button' という文字列が最初から入っています
import AppKit, objc
STYLES = dict(
Rounded = AppKit.NSBezelStyleRounded, #1
RegularSquare = AppKit.NSBezelStyleRegularSquare, #2
ShadowlessSquare = AppKit.NSBezelStyleShadowlessSquare, #6
TexturedSquare = AppKit.NSBezelStyleTexturedSquare, #8
SmallSquare = AppKit.NSBezelStyleSmallSquare, #10
TexturedRounded = AppKit.NSBezelStyleTexturedRounded, #11
RoundRect = AppKit.NSBezelStyleRoundRect, #12
Recessed = AppKit.NSBezelStyleRecessed, #13
Inline = AppKit.NSBezelStyleInline #15
)
IMGSTYLES = [
AppKit.NSBezelStyleDisclosure, #5
AppKit.NSBezelStyleCircular, #7
AppKit.NSBezelStyleHelpButton, #9
AppKit.NSBezelStyleRoundedDisclosure, #14
]
class ButtonView(AppKit.NSView):
def initWithFrame_(self, rect):
objc.super(ButtonView, self).initWithFrame_(rect)
#
y = 10
for key, style in STYLES.items():
button = AppKit.NSButton.alloc().initWithFrame_(((10, y), (200, 36)))
button.setTitle_(key)
button.setBezelStyle_(style)
self.addSubview_(button)
y += 40
for style in IMGSTYLES:
button = AppKit.NSButton.alloc().initWithFrame_(((10, y), (200, 36)))
button.setTitle_('') # Button という文字列が最初に入っているので消す
button.setBezelStyle_(style)
self.addSubview_(button)
y += 40
#
return self
def isFlipped(self):
# 左上を原点にする
return True
class MyWindow(AppKit.NSWindow):
def init(self):
rect = AppKit.NSMakeRect(0, 0, 220, 550)
objc.super(MyWindow, self).initWithContentRect_styleMask_backing_defer_(
rect,
AppKit.NSTitledWindowMask |
AppKit.NSClosableWindowMask |
AppKit.NSResizableWindowMask |
AppKit.NSMiniaturizableWindowMask,
AppKit.NSBackingStoreBuffered, False)
# NSView
self.canvas = ButtonView.alloc().initWithFrame_(rect)
self.contentView().addSubview_(self.canvas)
# etc
self.setTitle_('NSButton Styles')
self.setDelegate_(self)
return self
def windowDidResize_(self, sender):
# GTK+ や WPF のように追従してくれないので
self.canvas.setFrameSize_(self.contentView().frame().size)
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()

ボタンタイプ
ON|OFF ボタンやラジオボタンもすべて NSButton の type で指定して作ります。どんなタイプがあるか、やはり作って確認したほうが早いので以下に。
#!/usr/bin/env python3
import AppKit, objc
STYLES = dict(
# 普通のボタン、違いはわからない(昔は違いがあった?)
MomentaryLight = AppKit.NSButtonTypeMomentaryLight, #0
MomentaryPushIn = AppKit.NSButtonTypeMomentaryPushIn, #7
# 押す毎に ON|OFF を切り替え、GtkToggleButton と同じ、違いはわからない
PushOnPushOff = AppKit.NSButtonTypePushOnPushOff, #1
OnOff = AppKit.NSButtonTypeOnOff, #6
# ON 状態の時に違うテキストをタイトルにしたい場合に、GtkToggleButton とは違う
Toggle = AppKit.NSButtonTypeToggle, #2
# GTK+ でいう GtkCheckButton、紛らわしい
Switch = AppKit.NSButtonTypeSwitch, #3
# ラジオボタン、NSMatrix と組み合わせで使う
Radio = AppKit.NSButtonTypeRadio, #4
# ON 状態の時に違う画像をタイトルにしたい場合
MomentaryChange = AppKit.NSButtonTypeMomentaryChange, #5
# 感圧トラックパッドの圧力を得る時に使う
Accelerator = AppKit.NSButtonTypeAccelerator, #8
MultiLevelAccelerator = AppKit.NSButtonTypeMultiLevelAccelerator #9
)
class ButtonView(AppKit.NSView):
def initWithFrame_(self, rect):
objc.super(ButtonView, self).initWithFrame_(rect)
#
y = 10
for key, button_type in STYLES.items():
# メッセージハンドラは self のメソッドにする、コロンとアンダーバーに注意
button = AppKit.NSButton.buttonWithTitle_target_action_(key, self, 'onButtonClick:')
button.setFrame_(((10, y), (200, 36)))
button.setBezelStyle_(AppKit.NSBezelStyleRounded)
button.setButtonType_(button_type)
# 代替タイトル、Toggle 指定の時だけ切り替わる
button.setAlternateTitle_('ON!!!')
# 代替画像、MomentaryChange 指定の時だけ入れ替わる
#button.setAlternateImage_(image)
self.addSubview_(button)
y += 40
#
return self
def onButtonClick_(self, sender):
# ボタンクリックのハンドラ
if sender.state() == AppKit.NSControlStateValueOn:
print(sender.title())
# 感圧トラックパッドで Accelerator ボタン押し込み時のみ反応する
tp = sender.doubleValue()
if 1.0 < tp:
print(tp)
def isFlipped(self):
# 左上を原点にする
return True
class MyWindow(AppKit.NSWindow):
def init(self):
rect = AppKit.NSMakeRect(0, 0, 220, 420)
objc.super(MyWindow, self).initWithContentRect_styleMask_backing_defer_(
rect,
AppKit.NSTitledWindowMask |
AppKit.NSClosableWindowMask |
AppKit.NSResizableWindowMask |
AppKit.NSMiniaturizableWindowMask,
AppKit.NSBackingStoreBuffered, False)
# NSView
self.canvas = ButtonView.alloc().initWithFrame_(rect)
self.contentView().addSubview_(self.canvas)
# etc
self.setTitle_('NSButton Types')
self.setDelegate_(self)
return self
def windowDidResize_(self, sender):
# GTK+ や WPF のように追従してくれないので
self.canvas.setFrameSize_(self.contentView().frame().size)
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()

ラジオボタン (NSMatrix)
ラジオボタンは複数の選択肢から一つを選択させるのに利用します。NSMatrix と組み合わせて使います、以下サンプル。
#!/usr/bin/env python3
import AppKit, objc
CAMERAS = ['OM SYSTEM', 'Leica', 'NIKON', 'FUJIFILM']
class ButtonView(AppKit.NSView):
def initWithFrame_(self, rect):
objc.super(ButtonView, self).initWithFrame_(rect)
#
# Radio Buttons
#
# セルを作る
cell = AppKit.NSButtonCell.new()
cell.setButtonType_(AppKit.NSButtonTypeRadio)
# 全体サイズでマトリクス作成
self.matrix = AppKit.NSMatrix.alloc().initWithFrame_mode_prototype_numberOfRows_numberOfColumns_(
((10, 10), (200, 20*4)), AppKit.NSRadioModeMatrix, cell, 4, 1)
for n, camera in enumerate(CAMERAS):
self.matrix.setCellSize_((200, 20))
self.matrix.cells()[n].setTitle_(camera)
# 選択は setState 引数にゼロ以外を指定
self.matrix.setState_atRow_column_(1, 2, 0)
self.addSubview_(self.matrix)
#
return self
def isFlipped(self):
# 左上を原点にする
return True
class MyWindow(AppKit.NSWindow):
def init(self):
rect = AppKit.NSMakeRect(0, 0, 220, 200)
objc.super(MyWindow, self).initWithContentRect_styleMask_backing_defer_(
rect,
AppKit.NSTitledWindowMask |
AppKit.NSClosableWindowMask |
AppKit.NSResizableWindowMask |
AppKit.NSMiniaturizableWindowMask,
AppKit.NSBackingStoreBuffered, False)
# NSView
self.canvas = ButtonView.alloc().initWithFrame_(rect)
self.contentView().addSubview_(self.canvas)
# etc
self.setTitle_('NSButton Matrix')
self.setDelegate_(self)
return self
def windowDidResize_(self, sender):
# GTK+ や WPF のように追従してくれないので
self.canvas.setFrameSize_(self.contentView().frame().size)
def windowWillClose_(self, sender):
# 選択値はゼロベースで得る
row = self.canvas.matrix.selectedRow()
print(f'選択されたのは {CAMERAS[row]} です')
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.