2016-09-19 2 views
1

인터페이스를 설명하는 Glade 파일이 있습니다. 그 목표는 로컬 네트워크를 통해 Nec 모니터를 제어하는 ​​것입니다. 모니터의 작동 방식을 따라서 제어 위젯 많이 있습니다 : 나는/얻을 모니터와 위젯 /에서 설정 한 것 사이의 링크를 생성 할 필요가Haskell + GTK에서 위젯을 다루는 방법은 무엇입니까?

enter image description here

. 이것은 값을 가져 오거나 설정하고 함수를 위젯에 연결하는 것을 의미합니다.

GTK 라이브러리의 Builder은 IO()를 사용하고 특정 기능을 호출하기 위해 모든 위젯을 캐스팅해야합니다. 이것은 다소 지루하고 불필요한 코드 행을 추가합니다.

module GUI where 

import Graphics.UI.Gtk 

data NecControlGUI = NecControlGUI 
    { winNecControl :: Window 
    , entIPAddress :: Entry 
    , btnConnection :: Button 
    , cbtVideoInput :: ComboBox 
    , cbtPIPInput :: ComboBox 
    , sclSharpness :: Scale 
    , sclContrast :: Scale 
    , sclBrightness :: Scale 
    , sclBlackLevel :: Scale 
    , sclColorTemperature :: Scale 
    , cbtGamma :: ComboBox 
    , sclBalance :: Scale 
    , sclTreble :: Scale 
    , sclBass :: Scale 
    , sclVolume :: Scale 
    , cbtLanguage :: ComboBox 
    , sclMenuDisplayTime :: Scale 
    } 

loadGUI :: String -> IO NecControlGUI 
loadGUI guiPath = do 
    bdr <- builderNew 

    builderAddFromFile bdr guiPath 

    window <- builderGetObject bdr castToWindow "winNecControl" 
    ipaddress <- builderGetObject bdr castToEntry "entIPAddress" 
    connection <- builderGetObject bdr castToButton "btnConnection" 
    videoinput <- builderGetObject bdr castToComboBox "cbtVideoInput" 
    pipinput <- builderGetObject bdr castToComboBox "cbtPIPInput" 
    sharpness <- builderGetObject bdr castToScale "sclSharpness" 
    contrast <- builderGetObject bdr castToScale "sclContrast" 
    brightness <- builderGetObject bdr castToScale "sclBrightness" 
    blacklevel <- builderGetObject bdr castToScale "sclBlackLevel" 
    colortemperature <- builderGetObject bdr castToScale "sclColorTemparature" 
    gamma <- builderGetObject bdr castToComboBox "cbtGamma" 
    balance <- builderGetObject bdr castToScale "sclBalance" 
    treble <- builderGetObject bdr castToScale "sclTreble" 
    bass <- builderGetObject bdr castToScale "sclBass" 
    volume <- builderGetObject bdr castToScale "sclVolume" 
    language <- builderGetObject bdr castToComboBox "cbtLanguage" 
    menudisplaytime <- builderGetObject bdr castToScale "sclMenuDisplayTime" 

    return NecControlGUI 
     { winNecControl = window 
     , entIPAddress = ipaddress 
     , btnConnection = connection 
     , cbtVideoInput = videoinput 
     , cbtPIPInput = pipinput 
     , sclSharpness = sharpness 
     , sclContrast = contrast 
     , sclBrightness = brightness 
     , sclBlackLevel = blacklevel 
     , sclColorTemperature = colortemperature 
     , cbtGamma = gamma 
     , sclBalance = balance 
     , sclTreble = treble 
     , sclBass = bass 
     , sclVolume = volume 
     , cbtLanguage = language 
     , sclMenuDisplayTime = menudisplaytime 
     } 

이 부분을 자동화하는 방법이 있습니까?

나는 LGtk에 대해 들어 봤지만 그것을하는 유일한 방법 일까?

나는 실용적 길을 갈하려고 2016년 9월 20일 1

편집,하지만 실용적 IO를 결합처럼 그 하스켈을하지 않는 것?

.../src/NecControlGUI.hs:16:23: error: 
    • Couldn't match type ‘Adjustment’ with ‘Window’ 
     Expected type: IO Window 
     Actual type: IO Adjustment 
    • In the second argument of ‘(<*>)’, namely 
     ‘bget castToWindow "winNecControl"’ 
     In a stmt of a 'do' block: 
     NecControlGUI <$> bget castToAdjustment "adjBalance" 
     <*> bget castToWindow "winNecControl" 
     In the expression: 
     do { bdr <- builderNew; 
      builderAddFromFile bdr guiPath; 
      let bget = builderGetObject bdr; 
      NecControlGUI <$> bget castToAdjustment "adjBalance" 
      <*> bget castToWindow "winNecControl" } 

.../src/NecControlGUI.hs:16:28: error: 
    • Couldn't match type ‘Window’ with ‘Adjustment’ 
     Expected type: GObject -> Adjustment 
     Actual type: GObject -> Window 
    • In the first argument of ‘bget’, namely ‘castToWindow’ 
     In the second argument of ‘(<*>)’, namely 
     ‘bget castToWindow "winNecControl"’ 
     In a stmt of a 'do' block: 
     NecControlGUI <$> bget castToAdjustment "adjBalance" 
     <*> bget castToWindow "winNecControl" 

편집 나는 let bdr = ... 문, 모든 작업을 제거하면 2016년 9월 20일 2

을 다음 오류 출력을 컴파일

module NecControlGUI where 

import Graphics.UI.Gtk 

data NecControlGUI = NecControlGUI 
    { adjBalance :: Adjustment 
    , winNecControl :: Window 
    } 

loadNecControlGUI :: String -> IO NecControlGUI 
loadNecControlGUI guiPath = do 
    bdr <- builderNew 
    builderAddFromFile bdr guiPath 
    let bget = builderGetObject bdr 
    NecControlGUI <$> bget castToAdjustment "adjBalance" 
        <*> bget castToWindow "winNecControl" 

(하지만 아마 나에게있어) 예상대로

+0

두 가지 즉각적인 개선점은'bget = builderGetObject bdr'을 정의하고 한 번만 사용되는 임시 이름 정의를 중지하는 것입니다. 'return NecControlGUI {winNetControl = bget castToWindow "winNecControl", ...}' – chepner

+0

흠, 확실하지 않지만 LGtk에서 Glade 파일을 지원하지 않는다고 생각하면 LGtk 구문으로 처음부터 GUI를 정의해야 할 것입니다. Glade를 사용하여 꽤 복잡한 GUI를 만들었고 복사 붙여 넣기 및 검색/바꾸기로이 작업을 많이했습니다. 확실히, 그것은 지루하지만, 어떻게 든 당신은 어떤 타입과 값으로 glade 파일의 내용을 연관시켜야합니다. glade 파일에서 뭔가를 가져 와서 레코드 필드에 넣고 Glade의 기본 명명 규칙을 사용하는 표준 경우 만 있다면 Haskell 코드 생성기를 작성할 수 있지만 그만한 가치가 있다면 ... – MichaelO

+0

@chepner'builderGetObject'는 모나드 값을 반환하고 레코드 구조는 순수한 값으로 작동하기 때문에 임시 이름을 사용할 수 없습니다. – zigazou

답변

1

찾고있는 것이 아니지만 짧습니다. Applicative 인스턴스를 사용하여 builderGetObject에 대한 호출을 데이터 생성자와 결합하십시오.

module GUI where 

import Graphics.UI.Gtk 

data NecControlGUI = NecControlGUI 
    { ... 
    } 

loadGUI :: String -> IO NecControlGUI 
loadGUI guiPath = do 
    bdr <- builderNew 

    builderAddFromFile bdr guiPath 

    let bget = builderGetObject bdr 

    NecControlGUI <$> bget castToWindow "winNecControl" 
        <*> bget castToEntry "entIPAddress" 
        <*> bget castToButton "btnConnection" 
        <*> bget castToComboBox "cbtVideoInput" 
        <*> bget castToComboBox "cbtPIPInput" 
        <*> bget castToScale "sclSharpness" 
        <*> bget castToScale "sclContrast" 
        <*> bget castToScale "sclBrightness" 
        <*> bget castToScale "sclBlackLevel" 
        <*> bget castToScale "sclColorTemparature" 
        <*> bget castToComboBox "cbtGamma" 
        <*> bget castToScale "sclBalance" 
        <*> bget castToScale "sclTreble" 
        <*> bget castToScale "sclBass" 
        <*> bget castToScale "sclVolume" 
        <*> bget castToComboBox "cbtLanguage" 
        <*> bget castToScale "sclMenuDisplayTime" 
+0

나는 응용 방식을 시도했지만 작동하지 않는 것 같아서 왜 그런지 모르겠다. -/ – zigazou

+0

레코드 구문을 "일반"구문으로 전환하면 어떻게됩니까? 'data NecControlGUI = NecControlGUI Adjustment Window'? – chepner

+0

정확히 동일합니다! builderGetObject에 의한 형변환 함수의 사용이 문제의 원인 일 수 있습니까? – zigazou

관련 문제